-

enum class e

-
    -
  • X
  • -
+ + + + + + + + + + + + +
enum class e
X0

Defined at line 10 diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index c251c46a04adf43..4da99e899e7f7ce 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -319,6 +319,12 @@ def __eq__(self, other): def __ne__(self, other): return not self.__eq__(other) + def __lt__(self, other: SourceLocation) -> bool: + return conf.lib.clang_isBeforeInTranslationUnit(self, other) # type: ignore [no-any-return] + + def __le__(self, other: SourceLocation) -> bool: + return self < other or self == other + def __repr__(self): if self.file: filename = self.file.name @@ -375,26 +381,7 @@ def __contains__(self, other): """Useful to detect the Token/Lexer bug""" if not isinstance(other, SourceLocation): return False - if other.file is None and self.start.file is None: - pass - elif ( - self.start.file.name != other.file.name - or other.file.name != self.end.file.name - ): - # same file name - return False - # same file, in between lines - if self.start.line < other.line < self.end.line: - return True - elif self.start.line == other.line: - # same file first line - if self.start.column <= other.column: - return True - elif other.line == self.end.line: - # same file last line - if other.column <= self.end.column: - return True - return False + return self.start <= other <= self.end def __repr__(self): return "" % (self.start, self.end) @@ -3908,6 +3895,7 @@ def write_main_file_to_stdout(self): ("clang_isUnexposed", [CursorKind], bool), ("clang_isVirtualBase", [Cursor], bool), ("clang_isVolatileQualifiedType", [Type], bool), + ("clang_isBeforeInTranslationUnit", [SourceLocation, SourceLocation], bool), ( "clang_parseTranslationUnit", [Index, c_interop_string, c_void_p, c_int, c_void_p, c_int, c_int], diff --git a/clang/bindings/python/tests/cindex/test_location.py b/clang/bindings/python/tests/cindex/test_location.py index e23677a9be3c095..27854a312e6721d 100644 --- a/clang/bindings/python/tests/cindex/test_location.py +++ b/clang/bindings/python/tests/cindex/test_location.py @@ -130,3 +130,23 @@ def test_is_system_location(self): two = get_cursor(tu, "two") self.assertFalse(one.location.is_in_system_header) self.assertTrue(two.location.is_in_system_header) + + def test_operator_lt(self): + tu = get_tu("aaaaa") + t1_f = tu.get_file(tu.spelling) + tu2 = get_tu("aaaaa") + + l_t1_12 = SourceLocation.from_position(tu, t1_f, 1, 2) + l_t1_13 = SourceLocation.from_position(tu, t1_f, 1, 3) + l_t1_14 = SourceLocation.from_position(tu, t1_f, 1, 4) + + l_t2_13 = SourceLocation.from_position(tu2, tu2.get_file(tu2.spelling), 1, 3) + + # In same file + assert l_t1_12 < l_t1_13 < l_t1_14 + assert not l_t1_13 < l_t1_12 + + # In same file, different TU + assert l_t1_12 < l_t2_13 < l_t1_14 + assert not l_t2_13 < l_t1_12 + assert not l_t1_14 < l_t2_13 diff --git a/clang/bindings/python/tests/cindex/test_source_range.py b/clang/bindings/python/tests/cindex/test_source_range.py new file mode 100644 index 000000000000000..47d8960fcafb352 --- /dev/null +++ b/clang/bindings/python/tests/cindex/test_source_range.py @@ -0,0 +1,85 @@ +import os +from clang.cindex import Config + +if "CLANG_LIBRARY_PATH" in os.environ: + Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"]) + +import unittest +from clang.cindex import SourceLocation, SourceRange, TranslationUnit + +from .util import get_tu + + +def create_range(tu, line1, column1, line2, column2): + return SourceRange.from_locations( + SourceLocation.from_position(tu, tu.get_file(tu.spelling), line1, column1), + SourceLocation.from_position(tu, tu.get_file(tu.spelling), line2, column2), + ) + + +class TestSourceRange(unittest.TestCase): + def test_contains(self): + tu = get_tu( + """aaaaa +aaaaa +aaaaa +aaaaa""" + ) + file = tu.get_file(tu.spelling) + + l13 = SourceLocation.from_position(tu, file, 1, 3) + l21 = SourceLocation.from_position(tu, file, 2, 1) + l22 = SourceLocation.from_position(tu, file, 2, 2) + l23 = SourceLocation.from_position(tu, file, 2, 3) + l24 = SourceLocation.from_position(tu, file, 2, 4) + l25 = SourceLocation.from_position(tu, file, 2, 5) + l33 = SourceLocation.from_position(tu, file, 3, 3) + l31 = SourceLocation.from_position(tu, file, 3, 1) + r22_24 = create_range(tu, 2, 2, 2, 4) + r23_23 = create_range(tu, 2, 3, 2, 3) + r24_32 = create_range(tu, 2, 4, 3, 2) + r14_32 = create_range(tu, 1, 4, 3, 2) + + assert l13 not in r22_24 # Line before start + assert l21 not in r22_24 # Column before start + assert l22 in r22_24 # Colum on start + assert l23 in r22_24 # Column in range + assert l24 in r22_24 # Column on end + assert l25 not in r22_24 # Column after end + assert l33 not in r22_24 # Line after end + + assert l23 in r23_23 # In one-column range + + assert l23 not in r24_32 # Outside range in first line + assert l33 not in r24_32 # Outside range in last line + assert l25 in r24_32 # In range in first line + assert l31 in r24_32 # In range in last line + + assert l21 in r14_32 # In range at start of center line + assert l25 in r14_32 # In range at end of center line + + # In range within included file + tu2 = TranslationUnit.from_source( + "main.c", + unsaved_files=[ + ( + "main.c", + """int a[] = { +#include "numbers.inc" +}; +""", + ), + ( + "./numbers.inc", + """1, +2, +3, +4 + """, + ), + ], + ) + + r_curly = create_range(tu2, 1, 11, 3, 1) + l_f2 = SourceLocation.from_position(tu2, tu2.get_file("./numbers.inc"), 4, 1) + assert l_f2 in r_curly diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 72e1bd19b6b520f..c79a635d86a6ef8 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -4187,7 +4187,8 @@ the configuration (without a prefix: ``Auto``). **IndentRequiresClause** (``Boolean``) :versionbadge:`clang-format 15` :ref:`ΒΆ ` Indent the requires clause in a template. This only applies when - ``RequiresClausePosition`` is ``OwnLine``, or ``WithFollowing``. + ``RequiresClausePosition`` is ``OwnLine``, ``OwnLineWithBrace``, + or ``WithFollowing``. In clang-format 12, 13 and 14 it was named ``IndentRequires``. @@ -5419,23 +5420,48 @@ the configuration (without a prefix: ``Auto``). Possible values: * ``RCPS_OwnLine`` (in configuration: ``OwnLine``) - Always put the ``requires`` clause on its own line. + Always put the ``requires`` clause on its own line (possibly followed by + a semicolon). .. code-block:: c++ template - requires C + requires C struct Foo {... template - requires C + void bar(T t) + requires C; + + template + requires C void bar(T t) {... template void baz(T t) - requires C + requires C {... + * ``RCPS_OwnLineWithBrace`` (in configuration: ``OwnLineWithBrace``) + As with ``OwnLine``, except, unless otherwise prohibited, place a + following open brace (of a function definition) to follow on the same + line. + + .. code-block:: c++ + + void bar(T t) + requires C { + return; + } + + void bar(T t) + requires C {} + + template + requires C + void baz(T t) { + ... + * ``RCPS_WithPreceding`` (in configuration: ``WithPreceding``) Try to put the clause together with the preceding part of a declaration. For class templates: stick to the template declaration. diff --git a/clang/docs/ClangFormattedStatus.rst b/clang/docs/ClangFormattedStatus.rst index 68c13076ccbb4ec..0ee0782879ef6b4 100644 --- a/clang/docs/ClangFormattedStatus.rst +++ b/clang/docs/ClangFormattedStatus.rst @@ -439,7 +439,7 @@ tree in terms of conformance to :doc:`ClangFormat` as of: March 06, 2022 17:32:2 - `2` - `79` - :part:`2%` - * - clang/lib/AST/Interp + * - clang/lib/AST/ByteCode - `44` - `18` - `26` diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 4679dbb68b25e10..5b50ad615d2c99f 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1505,6 +1505,7 @@ Attributes on Lambda-Expressions C+ Attributes on Structured Bindings __cpp_structured_bindings C++26 C++03 Pack Indexing __cpp_pack_indexing C++26 C++03 ``= delete ("should have a reason");`` __cpp_deleted_function C++26 C++03 +Variadic Friends __cpp_variadic_friend C++26 C++03 -------------------------------------------- -------------------------------- ------------- ------------- Designated initializers (N494) C99 C89 Array & element qualification (N2607) C23 C89 @@ -3539,7 +3540,7 @@ the debugging experience. ``__builtin_allow_runtime_check`` --------------------------------- -``__builtin_allow_runtime_check`` return true if the check at the current +``__builtin_allow_runtime_check`` returns true if the check at the current program location should be executed. It is expected to be used to implement ``assert`` like checks which can be safely removed by optimizer. @@ -3559,28 +3560,25 @@ program location should be executed. It is expected to be used to implement **Description** -``__builtin_allow_runtime_check`` is lowered to ` ``llvm.allow.runtime.check`` +``__builtin_allow_runtime_check`` is lowered to the `llvm.allow.runtime.check `_ -builtin. - -The ``__builtin_allow_runtime_check()`` is expected to be used with control -flow conditions such as in ``if`` to guard expensive runtime checks. The -specific rules for selecting permitted checks can differ and are controlled by -the compiler options. - -Flags to control checks: -* ``-mllvm -lower-allow-check-percentile-cutoff-hot=N`` where N is PGO hotness -cutoff in range ``[0, 999999]`` to disallow checks in hot code. -* ``-mllvm -lower-allow-check-random-rate=P`` where P is number in range -``[0.0, 1.0]`` representation probability of keeping a check. -* If both flags are specified, ``-lower-allow-check-random-rate`` takes -precedence. -* If none is specified, ``__builtin_allow_runtime_check`` is lowered as -``true``, allowing all checks. - -Parameter ``kind`` is a string literal representing a user selected kind for -guarded check. It's unused now. It will enable kind-specific lowering in future. -E.g. a higher hotness cutoff can be used for more expensive kind of check. +intrinsic. + +The ``__builtin_allow_runtime_check()`` can be used within constrol structures +like ``if`` to guard expensive runtime checks. The return value is determined +by the following compiler options and may differ per call site: + +* ``-mllvm -lower-allow-check-percentile-cutoff-hot=N``: Disable checks in hot + code marked by the profile summary with a hotness cutoff in the range + ``[0, 999999]`` (a larger N disables more checks). +* ``-mllvm -lower-allow-check-random-rate=P``: Keep a check with probability P, + a floating point number in the range ``[0.0, 1.0]``. +* If both options are specified, a check is disabled if either condition is satisfied. +* If neither is specified, all checks are allowed. + +Parameter ``kind``, currently unused, is a string literal specifying the check +kind. Future compiler versions may use this to allow for more granular control, +such as applying different hotness cutoffs to different check kinds. Query for this feature with ``__has_builtin(__builtin_allow_runtime_check)``. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b1864901e7bddbc..249249971dec7ca 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -73,12 +73,10 @@ C++ Specific Potentially Breaking Changes template <> // error: extraneous template head template void f(); - + ABI Changes in This Version --------------------------- -- Fixed Microsoft name mangling of placeholder, auto and decltype(auto), return types for MSVC 1920+. This change resolves incompatibilities with code compiled by MSVC 1920+ but will introduce incompatibilities with code compiled by earlier versions of Clang unless such code is built with the compiler option -fms-compatibility-version=19.14 to imitate the MSVC 1914 mangling behavior. - AST Dumping Potentially Breaking Changes ---------------------------------------- @@ -92,6 +90,9 @@ Clang Python Bindings Potentially Breaking Changes - Calling a property on the ``CompletionChunk`` or ``CompletionString`` class statically now leads to an error, instead of returning a ``CachedProperty`` object that is used internally. Properties are only available on instances. +- For a single-line ``SourceRange`` and a ``SourceLocation`` in the same line, + but after the end of the ``SourceRange``, ``SourceRange.__contains__`` + used to incorrectly return ``True``. (#GH22617), (#GH52827) What's New in Clang |release|? ============================== @@ -128,6 +129,8 @@ C++2c Feature Support - Add ``__builtin_is_virtual_base_of`` intrinsic, which supports `P2985R0 A type trait for detecting virtual base classes `_ +- Implemented `P2893R3 Variadic Friends `_ + Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,6 +161,10 @@ C23 Feature Support Non-comprehensive list of changes in this release ------------------------------------------------- +- The floating point comparison builtins (``__builtin_isgreater``, + ``__builtin_isgreaterequal``, ``__builtin_isless``, etc.) and + ``__builtin_signbit`` can now be used in constant expressions. + New Compiler Flags ------------------ @@ -167,6 +174,8 @@ Deprecated Compiler Flags Modified Compiler Flags ----------------------- +- The compiler flag `-fbracket-depth` default value is increased from 256 to 2048. + Removed Compiler Flags ------------------------- @@ -186,6 +195,9 @@ Attribute Changes in Clang - The ``hybrid_patchable`` attribute is now supported on ARM64EC targets. It can be used to specify that a function requires an additional x86-64 thunk, which may be patched at runtime. +- ``[[clang::lifetimebound]]`` is now explicitly disallowed on explicit object member functions + where they were previously silently ignored. + Improvements to Clang's diagnostics ----------------------------------- @@ -211,6 +223,8 @@ Improvements to Clang's diagnostics - Clang now diagnoses the use of ``main`` in an ``extern`` context as invalid according to [basic.start.main] p3. Fixes #GH101512. +- Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391. + Improvements to Clang's time-trace ---------------------------------- @@ -256,10 +270,18 @@ Bug Fixes to C++ Support specialization of a conversion function template. - Correctly diagnose attempts to use a concept name in its own definition; A concept name is introduced to its scope sooner to match the C++ standard. (#GH55875) +- Properly reject defaulted relational operators with invalid types for explicit object parameters, + e.g., ``bool operator==(this int, const Foo&)`` (#GH100329), and rvalue reference parameters. +- Properly reject defaulted copy/move assignment operators that have a non-reference explicit object parameter. +- Clang now properly handles the order of attributes in `extern` blocks. (#GH101990). +- Fixed an assertion failure by preventing null explicit object arguments from being deduced. (#GH102025). +- Correctly check constraints of explicit instantiations of member functions. (#GH46029) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed a crash that occurred when dividing by zero in complex integer division. (#GH55390). + Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,6 +335,12 @@ Android Support Windows Support ^^^^^^^^^^^^^^^ +- Clang no longer allows references inside a union when emulating MSVC 1900+ even if `fms-extensions` is enabled. + Starting with VS2015, MSVC 1900, this Microsoft extension is no longer allowed and always results in an error. + Clang now follows the MSVC behavior in this scenario. + When `-fms-compatibility-version=18.00` or prior is set on the command line this Microsoft extension is still + allowed as VS2013 and prior allow it. + LoongArch Support ^^^^^^^^^^^^^^^^^ @@ -359,6 +387,8 @@ clang-format libclang -------- +- Add ``clang_isBeforeInTranslationUnit``. Given two source locations, it determines + whether the first one comes strictly before the second in the source code. Static Analyzer --------------- @@ -394,36 +424,6 @@ Moved checkers Sanitizers ---------- -- Added the ``-fsanitize-overflow-pattern-exclusion=`` flag which can be used - to disable specific overflow-dependent code patterns. The supported patterns - are: ``add-overflow-test``, ``negated-unsigned-const``, and - ``post-decr-while``. The sanitizer instrumentation can be toggled off for all - available patterns by specifying ``all``. Conversely, you can disable all - exclusions with ``none``. - - .. code-block:: c++ - - /// specified with ``-fsanitize-overflow-pattern-exclusion=add-overflow-test`` - int common_overflow_check_pattern(unsigned base, unsigned offset) { - if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented - } - - /// specified with ``-fsanitize-overflow-pattern-exclusion=negated-unsigned-const`` - void negation_overflow() { - unsigned long foo = -1UL; // No longer causes a negation overflow warning - unsigned long bar = -2UL; // and so on... - } - - /// specified with ``-fsanitize-overflow-pattern-exclusion=post-decr-while`` - void while_post_decrement() { - unsigned char count = 16; - while (count--) { /* ... */} // No longer causes unsigned-integer-overflow sanitizer to trip - } - - Many existing projects have a large amount of these code patterns present. - This new flag should allow those projects to enable integer sanitizers with - less noise. - Python Binding Changes ---------------------- - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``. diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 9f3d980eefbea77..531d56e313826c7 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -293,48 +293,6 @@ To silence reports from unsigned integer overflow, you can set ``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for providing fuzzing signal without blowing up logs. -Disabling instrumentation for common overflow patterns ------------------------------------------------------- - -There are certain overflow-dependent or overflow-prone code patterns which -produce a lot of noise for integer overflow/truncation sanitizers. Negated -unsigned constants, post-decrements in a while loop condition and simple -overflow checks are accepted and pervasive code patterns. However, the signal -received from sanitizers instrumenting these code patterns may be too noisy for -some projects. To disable instrumentation for these common patterns one should -use ``-fsanitize-overflow-pattern-exclusion=``. - -Currently, this option supports three overflow-dependent code idioms: - -``negated-unsigned-const`` - -.. code-block:: c++ - - /// -fsanitize-overflow-pattern-exclusion=negated-unsigned-const - unsigned long foo = -1UL; // No longer causes a negation overflow warning - unsigned long bar = -2UL; // and so on... - -``post-decr-while`` - -.. code-block:: c++ - - /// -fsanitize-overflow-pattern-exclusion=post-decr-while - unsigned char count = 16; - while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip - -``add-overflow-test`` - -.. code-block:: c++ - - /// -fsanitize-overflow-pattern-exclusion=add-overflow-test - if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, - // won't be instrumented (same for signed types) - -You can enable all exclusions with -``-fsanitize-overflow-pattern-exclusion=all`` or disable all exclusions with -``-fsanitize-overflow-pattern-exclusion=none``. Specifying ``none`` has -precedence over other values. - Issue Suppression ================= diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt index 62871133a680753..fc07357986d989f 100644 --- a/clang/docs/tools/clang-formatted-files.txt +++ b/clang/docs/tools/clang-formatted-files.txt @@ -322,24 +322,24 @@ clang/lib/APINotes/APINotesTypes.cpp clang/lib/APINotes/APINotesYAMLCompiler.cpp clang/lib/AST/DataCollection.cpp clang/lib/AST/Linkage.h -clang/lib/AST/Interp/ByteCodeGenError.cpp -clang/lib/AST/Interp/ByteCodeGenError.h -clang/lib/AST/Interp/Context.cpp -clang/lib/AST/Interp/Context.h -clang/lib/AST/Interp/Descriptor.cpp -clang/lib/AST/Interp/Disasm.cpp -clang/lib/AST/Interp/EvalEmitter.h -clang/lib/AST/Interp/Frame.cpp -clang/lib/AST/Interp/Frame.h -clang/lib/AST/Interp/InterpState.h -clang/lib/AST/Interp/Opcode.h -clang/lib/AST/Interp/Pointer.cpp -clang/lib/AST/Interp/PrimType.cpp -clang/lib/AST/Interp/Record.h -clang/lib/AST/Interp/Source.cpp -clang/lib/AST/Interp/Source.h -clang/lib/AST/Interp/State.cpp -clang/lib/AST/Interp/State.h +clang/lib/AST/ByteCode/ByteCodeGenError.cpp +clang/lib/AST/ByteCode/ByteCodeGenError.h +clang/lib/AST/ByteCode/Context.cpp +clang/lib/AST/ByteCode/Context.h +clang/lib/AST/ByteCode/Descriptor.cpp +clang/lib/AST/ByteCode/Disasm.cpp +clang/lib/AST/ByteCode/EvalEmitter.h +clang/lib/AST/ByteCode/Frame.cpp +clang/lib/AST/ByteCode/Frame.h +clang/lib/AST/ByteCode/InterpState.h +clang/lib/AST/ByteCode/Opcode.h +clang/lib/AST/ByteCode/Pointer.cpp +clang/lib/AST/ByteCode/PrimType.cpp +clang/lib/AST/ByteCode/Record.h +clang/lib/AST/ByteCode/Source.cpp +clang/lib/AST/ByteCode/Source.h +clang/lib/AST/ByteCode/State.cpp +clang/lib/AST/ByteCode/State.h clang/lib/ASTMatchers/GtestMatchers.cpp clang/lib/ASTMatchers/Dynamic/Marshallers.cpp clang/lib/Basic/Attributes.cpp diff --git a/clang/include/clang-c/CXSourceLocation.h b/clang/include/clang-c/CXSourceLocation.h index dcb13ba273173fd..421802151d02ab8 100644 --- a/clang/include/clang-c/CXSourceLocation.h +++ b/clang/include/clang-c/CXSourceLocation.h @@ -74,6 +74,16 @@ CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(void); CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2); +/** + * Determine for two source locations if the first comes + * strictly before the second one in the source code. + * + * \returns non-zero if the first source location comes + * strictly before the second one, zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_isBeforeInTranslationUnit(CXSourceLocation loc1, + CXSourceLocation loc2); + /** * Returns non-zero if the given source location is in a system header. */ diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 03657352c49a59e..baf63340640242a 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -141,6 +141,13 @@ class APINotesReader { ObjCSelectorRef Selector, bool IsInstanceMethod); + /// Look for information regarding the given field of a C struct. + /// + /// \param Name The name of the field. + /// + /// \returns information about the field, if known. + VersionedInfo lookupField(ContextID CtxID, llvm::StringRef Name); + /// Look for information regarding the given C++ method in the given C++ tag /// context. /// diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h index e0fe5eacef72582..3cc16c3d959faf6 100644 --- a/clang/include/clang/APINotes/APINotesWriter.h +++ b/clang/include/clang/APINotes/APINotesWriter.h @@ -86,6 +86,14 @@ class APINotesWriter { void addCXXMethod(ContextID CtxID, llvm::StringRef Name, const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion); + /// Add information about a specific C record field. + /// + /// \param CtxID The context in which this field resides, i.e. a C/C++ tag. + /// \param Name The name of the field. + /// \param Info Information about this field. + void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info, + llvm::VersionTuple SwiftVersion); + /// Add information about a global variable. /// /// \param Name The name of this global variable. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index f972d0cf26640d3..89889910d1a0730 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -656,6 +656,12 @@ class GlobalFunctionInfo : public FunctionInfo { GlobalFunctionInfo() {} }; +/// Describes API notes data for a C/C++ record field. +class FieldInfo : public VariableInfo { +public: + FieldInfo() {} +}; + /// Describes API notes data for a C++ method. class CXXMethodInfo : public FunctionInfo { public: diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 8e9b7ad8b468264..bd1851a26ce2e18 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -372,7 +372,7 @@ class ParamIdx { static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType), "ParamIdx does not fit its serialization type"); -#include "clang/AST/Attrs.inc" +#include "clang/AST/Attrs.inc" // IWYU pragma: export inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, const Attr *At) { diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index 26ae622e5b4496f..60ca1383f0a44ea 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -97,6 +97,10 @@ struct AvailabilityInfo { return UnconditionallyUnavailable; } + /// Augments the existing information with additional constraints provided by + /// \c Other. + void mergeWith(AvailabilityInfo Other); + AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, VersionTuple O, bool U, bool UD, bool UU) : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), diff --git a/clang/include/clang/AST/DeclFriend.h b/clang/include/clang/AST/DeclFriend.h index 9789282f351a55c..095f14a81fd5747 100644 --- a/clang/include/clang/AST/DeclFriend.h +++ b/clang/include/clang/AST/DeclFriend.h @@ -70,6 +70,9 @@ class FriendDecl final // Location of the 'friend' specifier. SourceLocation FriendLoc; + // Location of the '...', if present. + SourceLocation EllipsisLoc; + /// True if this 'friend' declaration is unsupported. Eventually we /// will support every possible friend declaration, but for now we /// silently ignore some and set this flag to authorize all access. @@ -82,10 +85,11 @@ class FriendDecl final unsigned NumTPLists : 31; FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, - SourceLocation FriendL, + SourceLocation FriendL, SourceLocation EllipsisLoc, ArrayRef FriendTypeTPLists) : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL), - UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) { + EllipsisLoc(EllipsisLoc), UnsupportedFriend(false), + NumTPLists(FriendTypeTPLists.size()) { for (unsigned i = 0; i < NumTPLists; ++i) getTrailingObjects()[i] = FriendTypeTPLists[i]; } @@ -110,7 +114,7 @@ class FriendDecl final static FriendDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, - SourceLocation FriendL, + SourceLocation FriendL, SourceLocation EllipsisLoc = {}, ArrayRef FriendTypeTPLists = std::nullopt); static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID, unsigned FriendTypeNumTPLists); @@ -143,8 +147,24 @@ class FriendDecl final return FriendLoc; } + /// Retrieves the location of the '...', if present. + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + /// Retrieves the source range for the friend declaration. SourceRange getSourceRange() const override LLVM_READONLY { + if (TypeSourceInfo *TInfo = getFriendType()) { + SourceLocation StartL = + (NumTPLists == 0) ? getFriendLoc() + : getTrailingObjects()[0] + ->getTemplateLoc(); + SourceLocation EndL = isPackExpansion() ? getEllipsisLoc() + : TInfo->getTypeLoc().getEndLoc(); + return SourceRange(StartL, EndL); + } + + if (isPackExpansion()) + return SourceRange(getFriendLoc(), getEllipsisLoc()); + if (NamedDecl *ND = getFriendDecl()) { if (const auto *FD = dyn_cast(ND)) return FD->getSourceRange(); @@ -158,15 +178,8 @@ class FriendDecl final } return SourceRange(getFriendLoc(), ND->getEndLoc()); } - else if (TypeSourceInfo *TInfo = getFriendType()) { - SourceLocation StartL = - (NumTPLists == 0) ? getFriendLoc() - : getTrailingObjects()[0] - ->getTemplateLoc(); - return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc()); - } - else - return SourceRange(getFriendLoc(), getLocation()); + + return SourceRange(getFriendLoc(), getLocation()); } /// Determines if this friend kind is unsupported. @@ -177,6 +190,8 @@ class FriendDecl final UnsupportedFriend = Unsupported; } + bool isPackExpansion() const { return EllipsisLoc.isValid(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::Friend; } diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index f5863524723a2ec..5b813bfc2faf908 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4043,15 +4043,6 @@ class BinaryOperator : public Expr { void setHasStoredFPFeatures(bool B) { BinaryOperatorBits.HasFPFeatures = B; } bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; } - /// Set and get the bit that informs arithmetic overflow sanitizers whether - /// or not they should exclude certain BinaryOperators from instrumentation - void setExcludedOverflowPattern(bool B) { - BinaryOperatorBits.ExcludedOverflowPattern = B; - } - bool hasExcludedOverflowPattern() const { - return BinaryOperatorBits.ExcludedOverflowPattern; - } - /// Get FPFeatures from trailing storage FPOptionsOverride getStoredFPFeatures() const { assert(hasStoredFPFeatures()); diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index f1a2aac0a8b2f8f..bbd7634bcc3bfb3 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -650,11 +650,6 @@ class alignas(void *) Stmt { LLVM_PREFERRED_TYPE(bool) unsigned HasFPFeatures : 1; - /// Whether or not this BinaryOperator should be excluded from integer - /// overflow sanitization. - LLVM_PREFERRED_TYPE(bool) - unsigned ExcludedOverflowPattern : 1; - SourceLocation OpLoc; }; diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index f9c923a36ad2296..ec4d041254877fd 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -139,6 +139,9 @@ struct ReferencedDecls { /// All variables with static storage duration, notably including static /// member variables and static variables declared within a function. llvm::DenseSet Globals; + /// Local variables, not including parameters or static variables declared + /// within a function. + llvm::DenseSet Locals; /// Free functions and member functions which are referenced (but not /// necessarily called). llvm::DenseSet Functions; diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 0a874d8638df435..036366cdadf4aa2 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -533,42 +533,42 @@ def BuiltinComplex : Builtin { def IsGreater : Builtin { let Spellings = ["__builtin_isgreater"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } def IsGreaterEqual : Builtin { let Spellings = ["__builtin_isgreaterequal"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } def IsLess : Builtin { let Spellings = ["__builtin_isless"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } def IsLessEqual : Builtin { let Spellings = ["__builtin_islessequal"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } def IsLessGreater : Builtin { let Spellings = ["__builtin_islessgreater"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } def IsUnordered : Builtin { let Spellings = ["__builtin_isunordered"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } @@ -646,19 +646,21 @@ def IsFPClass : Builtin { def Signbit : Builtin { let Spellings = ["__builtin_signbit"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, - CustomTypeChecking]; + CustomTypeChecking, Constexpr]; let Prototype = "int(...)"; } def SignbitF : Builtin { let Spellings = ["__builtin_signbitf"]; - let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const]; + let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, + Constexpr]; let Prototype = "int(float)"; } def SignbitL : Builtin { let Spellings = ["__builtin_signbitl"]; - let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const]; + let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, + Constexpr]; let Prototype = "int(long double)"; } diff --git a/clang/include/clang/Basic/BuiltinsNVPTX.def b/clang/include/clang/Basic/BuiltinsNVPTX.def index 504314d8d96e91e..c11970c279c4bba 100644 --- a/clang/include/clang/Basic/BuiltinsNVPTX.def +++ b/clang/include/clang/Basic/BuiltinsNVPTX.def @@ -584,6 +584,21 @@ TARGET_BUILTIN(__nvvm_f2bf16_rz_relu, "yf", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_f2tf32_rna, "ZUif", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_ff_to_e4m3x2_rn, "sff", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_ff_to_e4m3x2_rn_relu, "sff", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_ff_to_e5m2x2_rn, "sff", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_ff_to_e5m2x2_rn_relu, "sff", "", AND(SM_89,PTX81)) + +TARGET_BUILTIN(__nvvm_f16x2_to_e4m3x2_rn, "sV2h", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_f16x2_to_e4m3x2_rn_relu, "sV2h", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_f16x2_to_e5m2x2_rn, "sV2h", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_f16x2_to_e5m2x2_rn_relu, "sV2h", "", AND(SM_89,PTX81)) + +TARGET_BUILTIN(__nvvm_e4m3x2_to_f16x2_rn, "V2hs", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_e4m3x2_to_f16x2_rn_relu, "V2hs", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_e5m2x2_to_f16x2_rn, "V2hs", "", AND(SM_89,PTX81)) +TARGET_BUILTIN(__nvvm_e5m2x2_to_f16x2_rn_relu, "V2hs", "", AND(SM_89,PTX81)) + // Bitcast BUILTIN(__nvvm_bitcast_f2i, "if", "") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 5728ab8d86702be..09e892d6d4defea 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -37,8 +37,6 @@ VALUE_CODEGENOPT(Name, Bits, Default) CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as CODEGENOPT(Crel, 1, 0) ///< -Wa,--crel -CODEGENOPT(RelaxELFRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no} -CODEGENOPT(SSE2AVX , 1, 0) ///< -msse2avx CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments. CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new @@ -194,6 +192,8 @@ CODEGENOPT(HIPSaveKernelArgName, 1, 0) ///< Set when -fhip-kernel-arg-name is en CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names. CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using profile information. CODEGENOPT(PPCUseFullRegisterNames, 1, 0) ///< Print full register names in assembly +CODEGENOPT(X86RelaxRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no} +CODEGENOPT(X86Sse2Avx , 1, 0) ///< -Wa,-msse2avx /// When false, this attempts to generate code as if the result of an /// overflowing conversion matches the overflowing behavior of a target's native diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 92a602829933ced..ba90742fbdaabcf 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -604,9 +604,6 @@ def warn_drv_unsupported_gpopt : Warning< "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" " usage of }0-mabicalls">, InGroup; -def warn_drv_unsupported_sdata : Warning< - "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">, - InGroup; def warn_drv_unsupported_longcalls : Warning< "ignoring '-mlong-calls' option as it is not currently supported with " "%select{|the implicit usage of }0-mabicalls">, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 12aab09f285567f..62a97b36737e72e 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -965,6 +965,12 @@ def warn_cxx23_delete_with_message : Warning< "'= delete' with a message is incompatible with C++ standards before C++2c">, DefaultIgnore, InGroup; +def ext_variadic_friends : ExtWarn< + "variadic 'friend' declarations are a C++2c extension">, InGroup; +def warn_cxx23_variadic_friends : Warning< + "variadic 'friend' declarations are incompatible with C++ standards before C++2c">, + DefaultIgnore, InGroup; + // C++11 default member initialization def ext_nonstatic_member_init : ExtWarn< "default member initializer for non-static data member is a C++11 " diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index da2f939067bfab8..4b6aadd635786a9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1741,6 +1741,10 @@ def ext_friend_tag_redecl_outside_namespace : ExtWarn< "enclosing namespace is a Microsoft extension; add a nested name specifier">, InGroup; def err_pure_friend : Error<"friend declaration cannot have a pure-specifier">; +def err_friend_template_decl_multiple_specifiers: Error< + "a friend declaration that befriends a template must contain exactly one type-specifier">; +def friend_template_decl_malformed_pack_expansion : Error< + "friend declaration expands pack %0 that is declared it its own template parameter list">; def err_invalid_base_in_interface : Error< "interface type cannot inherit from " @@ -5663,6 +5667,8 @@ def err_explicit_instantiation_internal_linkage : Error< def err_explicit_instantiation_not_known : Error< "explicit instantiation of %0 does not refer to a function template, " "variable template, member function, member class, or static data member">; +def err_explicit_instantiation_no_candidate : Error< + "no viable candidate for explicit instantiation of %0">; def note_explicit_instantiation_here : Note< "explicit instantiation refers here">; def err_explicit_instantiation_data_member_not_instantiated : Error< @@ -9752,7 +9758,7 @@ def err_defaulted_special_member_quals : Error< "have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">; def err_defaulted_special_member_explicit_object_mismatch : Error< "the type of the explicit object parameter of an explicitly-defaulted " - "%select{copy|move}0 assignment operator should match the type of the class %1">; + "%select{copy|move}0 assignment operator should be reference to %1">; def err_defaulted_special_member_volatile_param : Error< "the parameter for an explicitly-defaulted %sub{select_special_member_kind}0 " "may not be volatile">; @@ -10062,8 +10068,9 @@ def warn_null_ret : Warning< InGroup; def err_lifetimebound_no_object_param : Error< - "'lifetimebound' attribute cannot be applied; %select{static |non-}0member " - "function has no implicit object parameter">; + "'lifetimebound' attribute cannot be applied; " + "%select{non-|static |explicit object }0" + "member function has no implicit object parameter">; def err_lifetimebound_ctor_dtor : Error< "'lifetimebound' attribute cannot be applied to a " "%select{constructor|destructor}0">; @@ -11160,6 +11167,8 @@ def err_omp_loop_diff_cxx : Error< "upper and lower loop bounds">; def err_omp_loop_cannot_use_stmt : Error< "'%0' statement cannot be used in OpenMP for loop">; +def err_omp_loop_bad_collapse_var : Error< + "cannot use variable %1 in collapsed imperfectly-nested loop %select{init|condition|increment}0 statement">; def err_omp_simd_region_cannot_use_stmt : Error< "'%0' statement cannot be used in OpenMP simd region">; def warn_omp_loop_64_bit_var : Warning< diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 2e9f2c552aad8a2..d454a7ff2f8cf49 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -406,8 +406,6 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0, "stop trivial automatic variable initialization if var size exceeds the specified size (in bytes). Must be greater than 0.") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") -LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation") -LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common overflow idioms") ENUM_LANGOPT(ThreadModel , ThreadModelKind, 2, ThreadModelKind::POSIX, "Thread Model") BENIGN_LANGOPT(ArrowDepth, 32, 256, diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index eb4cb4b5a7e93fa..91f1c2f2e6239ee 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -367,21 +367,6 @@ class LangOptionsBase { PerThread, }; - /// Exclude certain code patterns from being instrumented by arithmetic - /// overflow sanitizers - enum OverflowPatternExclusionKind { - /// Don't exclude any overflow patterns from sanitizers - None = 1 << 0, - /// Exclude all overflow patterns (below) - All = 1 << 1, - /// if (a + b < a) - AddOverflowTest = 1 << 2, - /// -1UL - NegUnsignedConst = 1 << 3, - /// while (count--) - PostDecrInWhile = 1 << 4, - }; - enum class DefaultVisiblityExportMapping { None, /// map only explicit default visibilities to exported @@ -570,11 +555,6 @@ class LangOptions : public LangOptionsBase { /// The default stream kind used for HIP kernel launching. GPUDefaultStreamKind GPUDefaultStream; - /// Which overflow patterns should be excluded from sanitizer instrumentation - unsigned OverflowPatternExclusionMask = 0; - - std::vector OverflowPatternExclusionValues; - /// The seed used by the randomize structure layout feature. std::string RandstructSeed; @@ -650,14 +630,6 @@ class LangOptions : public LangOptionsBase { return MSCompatibilityVersion >= MajorVersion * 100000U; } - bool isOverflowPatternExcluded(OverflowPatternExclusionKind Kind) const { - if (OverflowPatternExclusionMask & OverflowPatternExclusionKind::None) - return false; - if (OverflowPatternExclusionMask & OverflowPatternExclusionKind::All) - return true; - return OverflowPatternExclusionMask & Kind; - } - /// Reset all of the options that are not considered when building a /// module. void resetNonModularOptions(); diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index acc1f2fde53979a..c66e035a259b3ff 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2565,11 +2565,6 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats", "Disable">, BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>, Group; -def fsanitize_overflow_pattern_exclusion_EQ : CommaJoined<["-"], "fsanitize-overflow-pattern-exclusion=">, - HelpText<"Specify the overflow patterns to exclude from artihmetic sanitizer instrumentation">, - Visibility<[ClangOption, CC1Option]>, - Values<"none,all,add-overflow-test,negated-unsigned-const,post-decr-while">, - MarshallingInfoStringVector>; def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access">, Group, HelpText<"Enable memory access instrumentation in ThreadSanitizer (default)">; @@ -5236,7 +5231,7 @@ let Flags = [TargetSpecific] in { def msse2avx : Flag<["-"], "msse2avx">, Group, Visibility<[ClangOption, CC1Option, CC1AsOption]>, HelpText<"Specify that the assembler should encode SSE instructions with VEX prefix">, - MarshallingInfoFlag>; + MarshallingInfoFlag>; } // let Flags = [TargetSpecific] defm zvector : BoolFOption<"zvector", @@ -6149,6 +6144,10 @@ def mvis3 : Flag<["-"], "mvis3">, Group; def mno_vis3 : Flag<["-"], "mno-vis3">, Group; def mhard_quad_float : Flag<["-"], "mhard-quad-float">, Group; def msoft_quad_float : Flag<["-"], "msoft-quad-float">, Group; +def mv8plus : Flag<["-"], "mv8plus">, Group, + HelpText<"Enable V8+ mode, allowing use of 64-bit V9 instructions in 32-bit code">; +def mno_v8plus : Flag<["-"], "mno-v8plus">, Group, + HelpText<"Disable V8+ mode">; foreach i = 1 ... 7 in def ffixed_g#i : Flag<["-"], "ffixed-g"#i>, Group, HelpText<"Reserve the G"#i#" register (SPARC only)">; @@ -7134,7 +7133,7 @@ def crel : Flag<["--"], "crel">, MarshallingInfoFlag>; def mrelax_relocations_no : Flag<["-"], "mrelax-relocations=no">, HelpText<"Disable x86 relax relocations">, - MarshallingInfoNegativeFlag>; + MarshallingInfoNegativeFlag>; def msave_temp_labels : Flag<["-"], "msave-temp-labels">, HelpText<"Save temporary labels in the symbol table. " "Note this may change .s semantics and shouldn't generally be used " @@ -7960,7 +7959,7 @@ def fapply_global_visibility_to_externs : Flag<["-"], "fapply-global-visibility- MarshallingInfoFlag>; def fbracket_depth : Separate<["-"], "fbracket-depth">, HelpText<"Maximum nesting level for parentheses, brackets, and braces">, - MarshallingInfoInt, "256">; + MarshallingInfoInt, "2048">; defm const_strings : BoolOption<"f", "const-strings", LangOpts<"ConstStrings">, DefaultFalse, PosFlag, @@ -8841,7 +8840,7 @@ def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARA Visibility<[DXCOption, ClangOption, CC1Option]>, HelpText<"Override validator version for module. Format: ;" "Default: DXIL.dll version or current internal version">, - MarshallingInfoString>; + MarshallingInfoString, "\"1.8\"">; def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"">, HelpText<"Set target profile">, Values<"ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7," diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index e64ec463ca89070..47ef175302679f8 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -33,7 +33,6 @@ class SanitizerArgs { std::vector BinaryMetadataIgnorelistFiles; int CoverageFeatures = 0; int BinaryMetadataFeatures = 0; - int OverflowPatternExclusions = 0; int MsanTrackOrigins = 0; bool MsanUseAfterDtor = true; bool MsanParamRetval = true; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index ef6c76a070bfaaa..2af1d4065c3cc19 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2858,7 +2858,8 @@ struct FormatStyle { PPDirectiveIndentStyle IndentPPDirectives; /// Indent the requires clause in a template. This only applies when - /// ``RequiresClausePosition`` is ``OwnLine``, or ``WithFollowing``. + /// ``RequiresClausePosition`` is ``OwnLine``, ``OwnLineWithBrace``, + /// or ``WithFollowing``. /// /// In clang-format 12, 13 and 14 it was named ``IndentRequires``. /// \code @@ -3944,22 +3945,45 @@ struct FormatStyle { /// ``IndentRequires`` option is only used if the ``requires`` is put on the /// start of a line. enum RequiresClausePositionStyle : int8_t { - /// Always put the ``requires`` clause on its own line. + /// Always put the ``requires`` clause on its own line (possibly followed by + /// a semicolon). /// \code /// template - /// requires C + /// requires C /// struct Foo {... /// /// template - /// requires C + /// void bar(T t) + /// requires C; + /// + /// template + /// requires C /// void bar(T t) {... /// /// template /// void baz(T t) - /// requires C + /// requires C /// {... /// \endcode RCPS_OwnLine, + /// As with ``OwnLine``, except, unless otherwise prohibited, place a + /// following open brace (of a function definition) to follow on the same + /// line. + /// \code + /// void bar(T t) + /// requires C { + /// return; + /// } + /// + /// void bar(T t) + /// requires C {} + /// + /// template + /// requires C + /// void baz(T t) { + /// ... + /// \endcode + RCPS_OwnLineWithBrace, /// Try to put the clause together with the preceding part of a declaration. /// For class templates: stick to the template declaration. /// For function templates: stick to the template declaration. diff --git a/clang/include/clang/Rewrite/Core/DeltaTree.h b/clang/include/clang/Rewrite/Core/DeltaTree.h deleted file mode 100644 index e566c92aaff91ad..000000000000000 --- a/clang/include/clang/Rewrite/Core/DeltaTree.h +++ /dev/null @@ -1,50 +0,0 @@ -//===- DeltaTree.h - B-Tree for Rewrite Delta tracking ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the DeltaTree class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITE_CORE_DELTATREE_H -#define LLVM_CLANG_REWRITE_CORE_DELTATREE_H - -namespace clang { - - /// DeltaTree - a multiway search tree (BTree) structure with some fancy - /// features. B-Trees are generally more memory and cache efficient than - /// binary trees, because they store multiple keys/values in each node. This - /// implements a key/value mapping from index to delta, and allows fast lookup - /// on index. However, an added (important) bonus is that it can also - /// efficiently tell us the full accumulated delta for a specific file offset - /// as well, without traversing the whole tree. - class DeltaTree { - void *Root; // "DeltaTreeNode *" - - public: - DeltaTree(); - - // Note: Currently we only support copying when the RHS is empty. - DeltaTree(const DeltaTree &RHS); - - DeltaTree &operator=(const DeltaTree &) = delete; - ~DeltaTree(); - - /// getDeltaAt - Return the accumulated delta at the specified file offset. - /// This includes all insertions or delections that occurred *before* the - /// specified file index. - int getDeltaAt(unsigned FileIndex) const; - - /// AddDelta - When a change is made that shifts around the text buffer, - /// this method is used to record that info. It inserts a delta of 'Delta' - /// into the current DeltaTree at offset FileIndex. - void AddDelta(unsigned FileIndex, int Delta); - }; - -} // namespace clang - -#endif // LLVM_CLANG_REWRITE_CORE_DELTATREE_H diff --git a/clang/include/clang/Rewrite/Core/HTMLRewrite.h b/clang/include/clang/Rewrite/Core/HTMLRewrite.h index eecf589632746c1..9edb514d566b9c1 100644 --- a/clang/include/clang/Rewrite/Core/HTMLRewrite.h +++ b/clang/include/clang/Rewrite/Core/HTMLRewrite.h @@ -17,10 +17,13 @@ #include "clang/Basic/SourceLocation.h" #include +namespace llvm { +class RewriteBuffer; +} // namespace llvm + namespace clang { class Rewriter; -class RewriteBuffer; class Preprocessor; namespace html { @@ -53,9 +56,9 @@ namespace html { /// HighlightRange - This is the same as the above method, but takes /// decomposed file locations. - void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E, - const char *BufferStart, - const char *StartTag, const char *EndTag); + void HighlightRange(llvm::RewriteBuffer &RB, unsigned B, unsigned E, + const char *BufferStart, const char *StartTag, + const char *EndTag); /// EscapeText - HTMLize a specified file so that special characters are /// are translated so that they are not interpreted as HTML tags. diff --git a/clang/include/clang/Rewrite/Core/RewriteRope.h b/clang/include/clang/Rewrite/Core/RewriteRope.h deleted file mode 100644 index 73e66e111f57434..000000000000000 --- a/clang/include/clang/Rewrite/Core/RewriteRope.h +++ /dev/null @@ -1,223 +0,0 @@ -//===- RewriteRope.h - Rope specialized for rewriter ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the RewriteRope class, which is a powerful string class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H -#define LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H - -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringRef.h" -#include -#include -#include -#include - -namespace clang { - - //===--------------------------------------------------------------------===// - // RopeRefCountString Class - //===--------------------------------------------------------------------===// - - /// RopeRefCountString - This struct is allocated with 'new char[]' from the - /// heap, and represents a reference counted chunk of string data. When its - /// ref count drops to zero, it is delete[]'d. This is primarily managed - /// through the RopePiece class below. - struct RopeRefCountString { - unsigned RefCount; - char Data[1]; // Variable sized. - - void Retain() { ++RefCount; } - - void Release() { - assert(RefCount > 0 && "Reference count is already zero."); - if (--RefCount == 0) - delete [] (char*)this; - } - }; - - //===--------------------------------------------------------------------===// - // RopePiece Class - //===--------------------------------------------------------------------===// - - /// RopePiece - This class represents a view into a RopeRefCountString object. - /// This allows references to string data to be efficiently chopped up and - /// moved around without having to push around the string data itself. - /// - /// For example, we could have a 1M RopePiece and want to insert something - /// into the middle of it. To do this, we split it into two RopePiece objects - /// that both refer to the same underlying RopeRefCountString (just with - /// different offsets) which is a nice constant time operation. - struct RopePiece { - llvm::IntrusiveRefCntPtr StrData; - unsigned StartOffs = 0; - unsigned EndOffs = 0; - - RopePiece() = default; - RopePiece(llvm::IntrusiveRefCntPtr Str, unsigned Start, - unsigned End) - : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {} - - const char &operator[](unsigned Offset) const { - return StrData->Data[Offset+StartOffs]; - } - char &operator[](unsigned Offset) { - return StrData->Data[Offset+StartOffs]; - } - - unsigned size() const { return EndOffs-StartOffs; } - }; - - //===--------------------------------------------------------------------===// - // RopePieceBTreeIterator Class - //===--------------------------------------------------------------------===// - - /// RopePieceBTreeIterator - This class provides read-only forward iteration - /// over bytes that are in a RopePieceBTree. This first iterates over bytes - /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf, - /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree. - class RopePieceBTreeIterator { - /// CurNode - The current B+Tree node that we are inspecting. - const void /*RopePieceBTreeLeaf*/ *CurNode = nullptr; - - /// CurPiece - The current RopePiece in the B+Tree node that we're - /// inspecting. - const RopePiece *CurPiece = nullptr; - - /// CurChar - The current byte in the RopePiece we are pointing to. - unsigned CurChar = 0; - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = const char; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - RopePieceBTreeIterator() = default; - RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); - - char operator*() const { - return (*CurPiece)[CurChar]; - } - - bool operator==(const RopePieceBTreeIterator &RHS) const { - return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar; - } - bool operator!=(const RopePieceBTreeIterator &RHS) const { - return !operator==(RHS); - } - - RopePieceBTreeIterator& operator++() { // Preincrement - if (CurChar+1 < CurPiece->size()) - ++CurChar; - else - MoveToNextPiece(); - return *this; - } - - RopePieceBTreeIterator operator++(int) { // Postincrement - RopePieceBTreeIterator tmp = *this; ++*this; return tmp; - } - - llvm::StringRef piece() const { - return llvm::StringRef(&(*CurPiece)[0], CurPiece->size()); - } - - void MoveToNextPiece(); - }; - - //===--------------------------------------------------------------------===// - // RopePieceBTree Class - //===--------------------------------------------------------------------===// - - class RopePieceBTree { - void /*RopePieceBTreeNode*/ *Root; - - public: - RopePieceBTree(); - RopePieceBTree(const RopePieceBTree &RHS); - RopePieceBTree &operator=(const RopePieceBTree &) = delete; - ~RopePieceBTree(); - - using iterator = RopePieceBTreeIterator; - - iterator begin() const { return iterator(Root); } - iterator end() const { return iterator(); } - unsigned size() const; - unsigned empty() const { return size() == 0; } - - void clear(); - - void insert(unsigned Offset, const RopePiece &R); - - void erase(unsigned Offset, unsigned NumBytes); - }; - - //===--------------------------------------------------------------------===// - // RewriteRope Class - //===--------------------------------------------------------------------===// - -/// RewriteRope - A powerful string class. This class supports extremely -/// efficient insertions and deletions into the middle of it, even for -/// ridiculously long strings. -class RewriteRope { - RopePieceBTree Chunks; - - /// We allocate space for string data out of a buffer of size AllocChunkSize. - /// This keeps track of how much space is left. - llvm::IntrusiveRefCntPtr AllocBuffer; - enum { AllocChunkSize = 4080 }; - unsigned AllocOffs = AllocChunkSize; - -public: - RewriteRope() = default; - RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {} - - // The copy assignment operator is defined as deleted pending further - // motivation. - RewriteRope &operator=(const RewriteRope &) = delete; - - using iterator = RopePieceBTree::iterator; - using const_iterator = RopePieceBTree::iterator; - - iterator begin() const { return Chunks.begin(); } - iterator end() const { return Chunks.end(); } - unsigned size() const { return Chunks.size(); } - - void clear() { - Chunks.clear(); - } - - void assign(const char *Start, const char *End) { - clear(); - if (Start != End) - Chunks.insert(0, MakeRopeString(Start, End)); - } - - void insert(unsigned Offset, const char *Start, const char *End) { - assert(Offset <= size() && "Invalid position to insert!"); - if (Start == End) return; - Chunks.insert(Offset, MakeRopeString(Start, End)); - } - - void erase(unsigned Offset, unsigned NumBytes) { - assert(Offset+NumBytes <= size() && "Invalid region to erase!"); - if (NumBytes == 0) return; - Chunks.erase(Offset, NumBytes); - } - -private: - RopePiece MakeRopeString(const char *Start, const char *End); -}; - -} // namespace clang - -#endif // LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H diff --git a/clang/include/clang/Rewrite/Core/Rewriter.h b/clang/include/clang/Rewrite/Core/Rewriter.h index c89015e4055820c..4e96f6fcca919ce 100644 --- a/clang/include/clang/Rewrite/Core/Rewriter.h +++ b/clang/include/clang/Rewrite/Core/Rewriter.h @@ -16,7 +16,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/StringRef.h" #include #include @@ -32,7 +32,7 @@ class SourceManager; class Rewriter { SourceManager *SourceMgr = nullptr; const LangOptions *LangOpts = nullptr; - std::map RewriteBuffers; + std::map RewriteBuffers; public: struct RewriteOptions { @@ -49,7 +49,7 @@ class Rewriter { /// /// FIXME: This sometimes corrupts the file's rewrite buffer due to /// incorrect indexing in the implementation (see the FIXME in - /// clang::RewriteBuffer::RemoveText). Moreover, it's inefficient because + /// llvm::RewriteBuffer::RemoveText). Moreover, it's inefficient because /// it must scan the buffer from the beginning to find the start of the /// line. When feasible, it's better for the caller to check for a blank /// line and then, if found, expand the removal range to include it. @@ -62,8 +62,9 @@ class Rewriter { RewriteOptions() {} }; - using buffer_iterator = std::map::iterator; - using const_buffer_iterator = std::map::const_iterator; + using buffer_iterator = std::map::iterator; + using const_buffer_iterator = + std::map::const_iterator; explicit Rewriter() = default; explicit Rewriter(SourceManager &SM, const LangOptions &LO) @@ -191,13 +192,13 @@ class Rewriter { /// buffer, and allows you to write on it directly. This is useful if you /// want efficient low-level access to apis for scribbling on one specific /// FileID's buffer. - RewriteBuffer &getEditBuffer(FileID FID); + llvm::RewriteBuffer &getEditBuffer(FileID FID); /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID. /// If no modification has been made to it, return null. - const RewriteBuffer *getRewriteBufferFor(FileID FID) const { - std::map::const_iterator I = - RewriteBuffers.find(FID); + const llvm::RewriteBuffer *getRewriteBufferFor(FileID FID) const { + std::map::const_iterator I = + RewriteBuffers.find(FID); return I == RewriteBuffers.end() ? nullptr : &I->second; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a025ff6fc13f360..299a916b9abf8d9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -15,36 +15,42 @@ #define LLVM_CLANG_SEMA_SEMA_H #include "clang/APINotes/APINotesManager.h" -#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTFwd.h" #include "clang/AST/Attr.h" -#include "clang/AST/Availability.h" -#include "clang/AST/ComparisonCategories.h" +#include "clang/AST/AttrIterator.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/LocInfoType.h" -#include "clang/AST/MangleNumberingContext.h" -#include "clang/AST/NSAPI.h" -#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeOrdering.h" -#include "clang/Basic/BitmaskEnum.h" +#include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/CapturedStmt.h" #include "clang/Basic/Cuda.h" -#include "clang/Basic/DarwinSDKInfo.h" +#include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenCLOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/PragmaKinds.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Basic/TypeTraits.h" #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/Sema/Attr.h" @@ -52,124 +58,100 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/IdentifierResolver.h" -#include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Redeclaration.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" -#include "clang/Sema/SemaConcept.h" -#include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FloatingPointMode.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLForwardCompat.h" +#include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include +#include +#include #include +#include +#include #include #include #include #include +#include +#include #include namespace llvm { -class APSInt; -template class DenseSet; -class SmallBitVector; struct InlineAsmIdentifierInfo; } // namespace llvm namespace clang { class ADLResult; +class APValue; +struct ASTConstraintSatisfaction; class ASTConsumer; class ASTContext; +class ASTDeclReader; class ASTMutationListener; class ASTReader; class ASTWriter; -class ArrayType; -class ParsedAttr; -class BindingDecl; -class BlockDecl; -class CapturedDecl; class CXXBasePath; class CXXBasePaths; -class CXXBindTemporaryExpr; -typedef SmallVector CXXCastPath; -class CXXConstructorDecl; -class CXXConversionDecl; -class CXXDeleteExpr; -class CXXDestructorDecl; class CXXFieldCollector; -class CXXMemberCallExpr; -class CXXMethodDecl; -class CXXScopeSpec; -class CXXTemporary; -class CXXTryStmt; -class CallExpr; -class ClassTemplateDecl; -class ClassTemplatePartialSpecializationDecl; -class ClassTemplateSpecializationDecl; -class VarTemplatePartialSpecializationDecl; class CodeCompleteConsumer; -class CodeCompletionAllocator; -class CodeCompletionTUInfo; -class CodeCompletionResult; -class CoroutineBodyStmt; -class Decl; -class DeclAccessPair; -class DeclContext; -class DeclRefExpr; -class DeclaratorDecl; +enum class ComparisonCategoryType : unsigned char; +class ConstraintSatisfaction; +class DarwinSDKInfo; +class DeclGroupRef; class DeducedTemplateArgument; +struct DeductionFailureInfo; class DependentDiagnostic; -class DesignatedInitExpr; class Designation; -class EnableIfAttr; -class EnumConstantDecl; -class Expr; -class ExtVectorType; -class FormatAttr; -class FriendDecl; -class FunctionDecl; -class FunctionProtoType; -class FunctionTemplateDecl; +class IdentifierInfo; class ImplicitConversionSequence; typedef MutableArrayRef ConversionSequenceList; -class InitListExpr; class InitializationKind; class InitializationSequence; class InitializedEntity; -class IntegerLiteral; -class LabelStmt; -class LambdaExpr; -class LangOptions; +enum class LangAS : unsigned int; class LocalInstantiationScope; class LookupResult; -class MacroInfo; +class MangleNumberingContext; typedef ArrayRef> ModuleIdPath; class ModuleLoader; class MultiLevelTemplateArgumentList; -class NamedDecl; -class ObjCImplementationDecl; +struct NormalizedConstraint; class ObjCInterfaceDecl; class ObjCMethodDecl; -class ObjCProtocolDecl; struct OverloadCandidate; enum class OverloadCandidateParamOrder : char; enum OverloadCandidateRewriteKind : unsigned; class OverloadCandidateSet; -class OverloadExpr; -class ParenListExpr; -class ParmVarDecl; class Preprocessor; -class PseudoDestructorTypeStorage; -class PseudoObjectExpr; -class QualType; class SemaAMDGPU; class SemaARM; class SemaAVR; @@ -196,41 +178,19 @@ class SemaSystemZ; class SemaWasm; class SemaX86; class StandardConversionSequence; -class Stmt; -class StringLiteral; -class SwitchStmt; class TemplateArgument; -class TemplateArgumentList; class TemplateArgumentLoc; -class TemplateDecl; class TemplateInstantiationCallback; -class TemplateParameterList; class TemplatePartialOrderingContext; -class TemplateTemplateParmDecl; +class TemplateSpecCandidateSet; class Token; -class TypeAliasDecl; -class TypedefDecl; -class TypedefNameDecl; -class TypeLoc; +class TypeConstraint; class TypoCorrectionConsumer; -class UnqualifiedId; -class UnresolvedLookupExpr; -class UnresolvedMemberExpr; class UnresolvedSetImpl; class UnresolvedSetIterator; -class UsingDecl; -class UsingShadowDecl; -class ValueDecl; -class VarDecl; -class VarTemplateSpecializationDecl; -class VisibilityAttr; class VisibleDeclConsumer; -class IndirectFieldDecl; -struct DeductionFailureInfo; -class TemplateSpecCandidateSet; namespace sema { -class AccessedEntity; class BlockScopeInfo; class Capture; class CapturedRegionScopeInfo; @@ -240,8 +200,6 @@ class DelayedDiagnostic; class DelayedDiagnosticPool; class FunctionScopeInfo; class LambdaScopeInfo; -class PossiblyUnreachableDiag; -class RISCVIntrinsicManager; class SemaPPCallbacks; class TemplateDeductionInfo; } // namespace sema @@ -536,38 +494,40 @@ class Sema final : public SemaBase { // Table of Contents // ----------------- // 1. Semantic Analysis (Sema.cpp) - // 2. C++ Access Control (SemaAccess.cpp) - // 3. Attributes (SemaAttr.cpp) - // 4. Availability Attribute Handling (SemaAvailability.cpp) - // 5. Casts (SemaCast.cpp) - // 6. Extra Semantic Checking (SemaChecking.cpp) - // 7. C++ Coroutines (SemaCoroutine.cpp) - // 8. C++ Scope Specifiers (SemaCXXScopeSpec.cpp) - // 9. Declarations (SemaDecl.cpp) - // 10. Declaration Attribute Handling (SemaDeclAttr.cpp) - // 11. C++ Declarations (SemaDeclCXX.cpp) - // 12. C++ Exception Specifications (SemaExceptionSpec.cpp) - // 13. Expressions (SemaExpr.cpp) - // 14. C++ Expressions (SemaExprCXX.cpp) - // 15. Member Access Expressions (SemaExprMember.cpp) - // 16. Initializers (SemaInit.cpp) - // 17. C++ Lambda Expressions (SemaLambda.cpp) - // 18. Name Lookup (SemaLookup.cpp) - // 19. Modules (SemaModule.cpp) - // 20. C++ Overloading (SemaOverload.cpp) - // 21. Statements (SemaStmt.cpp) - // 22. `inline asm` Statement (SemaStmtAsm.cpp) - // 23. Statement Attribute Handling (SemaStmtAttr.cpp) - // 24. C++ Templates (SemaTemplate.cpp) - // 25. C++ Template Argument Deduction (SemaTemplateDeduction.cpp) - // 26. C++ Template Deduction Guide (SemaTemplateDeductionGuide.cpp) - // 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp) - // 28. C++ Template Declaration Instantiation + // 2. API Notes (SemaAPINotes.cpp) + // 3. C++ Access Control (SemaAccess.cpp) + // 4. Attributes (SemaAttr.cpp) + // 5. Availability Attribute Handling (SemaAvailability.cpp) + // 6. Bounds Safety (SemaBoundsSafety.cpp) + // 7. Casts (SemaCast.cpp) + // 8. Extra Semantic Checking (SemaChecking.cpp) + // 9. C++ Coroutines (SemaCoroutine.cpp) + // 10. C++ Scope Specifiers (SemaCXXScopeSpec.cpp) + // 11. Declarations (SemaDecl.cpp) + // 12. Declaration Attribute Handling (SemaDeclAttr.cpp) + // 13. C++ Declarations (SemaDeclCXX.cpp) + // 14. C++ Exception Specifications (SemaExceptionSpec.cpp) + // 15. Expressions (SemaExpr.cpp) + // 16. C++ Expressions (SemaExprCXX.cpp) + // 17. Member Access Expressions (SemaExprMember.cpp) + // 18. Initializers (SemaInit.cpp) + // 19. C++ Lambda Expressions (SemaLambda.cpp) + // 20. Name Lookup (SemaLookup.cpp) + // 21. Modules (SemaModule.cpp) + // 22. C++ Overloading (SemaOverload.cpp) + // 23. Statements (SemaStmt.cpp) + // 24. `inline asm` Statement (SemaStmtAsm.cpp) + // 25. Statement Attribute Handling (SemaStmtAttr.cpp) + // 26. C++ Templates (SemaTemplate.cpp) + // 27. C++ Template Argument Deduction (SemaTemplateDeduction.cpp) + // 28. C++ Template Deduction Guide (SemaTemplateDeductionGuide.cpp) + // 29. C++ Template Instantiation (SemaTemplateInstantiate.cpp) + // 30. C++ Template Declaration Instantiation // (SemaTemplateInstantiateDecl.cpp) - // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp) - // 30. Constraints and Concepts (SemaConcept.cpp) - // 31. Types (SemaType.cpp) - // 32. FixIt Helpers (SemaFixItUtils.cpp) + // 31. C++ Variadic Templates (SemaTemplateVariadic.cpp) + // 32. Constraints and Concepts (SemaConcept.cpp) + // 33. Types (SemaType.cpp) + // 34. FixIt Helpers (SemaFixItUtils.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -1325,6 +1285,25 @@ class Sema final : public SemaBase { // // + /// \name API Notes + /// Implementations are in SemaAPINotes.cpp + ///@{ + +public: + /// Map any API notes provided for this declaration to attributes on the + /// declaration. + /// + /// Triggered by declaration-attribute processing. + void ProcessAPINotes(Decl *D); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + /// \name C++ Access Control /// Implementations are in SemaAccess.cpp ///@{ @@ -2095,6 +2074,39 @@ class Sema final : public SemaBase { // // + /// \name Bounds Safety + /// Implementations are in SemaBoundsSafety.cpp + ///@{ +public: + /// Check if applying the specified attribute variant from the "counted by" + /// family of attributes to FieldDecl \p FD is semantically valid. If + /// semantically invalid diagnostics will be emitted explaining the problems. + /// + /// \param FD The FieldDecl to apply the attribute to + /// \param E The count expression on the attribute + /// \param CountInBytes If true the attribute is from the "sized_by" family of + /// attributes. If the false the attribute is from + /// "counted_by" family of attributes. + /// \param OrNull If true the attribute is from the "_or_null" suffixed family + /// of attributes. If false the attribute does not have the + /// suffix. + /// + /// Together \p CountInBytes and \p OrNull decide the attribute variant. E.g. + /// \p CountInBytes and \p OrNull both being true indicates the + /// `counted_by_or_null` attribute. + /// + /// \returns false iff semantically valid. + bool CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes, + bool OrNull); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + /// \name Casts /// Implementations are in SemaCast.cpp ///@{ @@ -3800,7 +3812,8 @@ class Sema final : public SemaBase { const ParsedAttributesView &DeclAttrs, MultiTemplateParamsArg TemplateParams, bool IsExplicitInstantiation, - RecordDecl *&AnonRecord); + RecordDecl *&AnonRecord, + SourceLocation EllipsisLoc = {}); /// BuildAnonymousStructOrUnion - Handle the declaration of an /// anonymous structure or union. Anonymous unions are a C++ feature @@ -5538,7 +5551,8 @@ class Sema final : public SemaBase { /// parameters present at all, require proper matching, i.e. /// template <> template \ friend class A::B; Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, - MultiTemplateParamsArg TemplateParams); + MultiTemplateParamsArg TemplateParams, + SourceLocation EllipsisLoc); NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParams); @@ -5852,6 +5866,7 @@ class Sema final : public SemaBase { unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + SourceLocation EllipsisLoc, const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists); @@ -15042,58 +15057,6 @@ class Sema final : public SemaBase { std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - - /// \name API Notes - /// Implementations are in SemaAPINotes.cpp - ///@{ - -public: - /// Map any API notes provided for this declaration to attributes on the - /// declaration. - /// - /// Triggered by declaration-attribute processing. - void ProcessAPINotes(Decl *D); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - - /// \name Bounds Safety - /// Implementations are in SemaBoundsSafety.cpp - ///@{ -public: - /// Check if applying the specified attribute variant from the "counted by" - /// family of attributes to FieldDecl \p FD is semantically valid. If - /// semantically invalid diagnostics will be emitted explaining the problems. - /// - /// \param FD The FieldDecl to apply the attribute to - /// \param E The count expression on the attribute - /// \param CountInBytes If true the attribute is from the "sized_by" family of - /// attributes. If the false the attribute is from - /// "counted_by" family of attributes. - /// \param OrNull If true the attribute is from the "_or_null" suffixed family - /// of attributes. If false the attribute does not have the - /// suffix. - /// - /// Together \p CountInBytes and \p OrNull decide the attribute variant. E.g. - /// \p CountInBytes and \p OrNull both being true indicates the - /// `counted_by_or_null` attribute. - /// - /// \returns false iff semantically valid. - bool CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes, - bool OrNull); - - ///@} }; DeductionFailureInfo diff --git a/clang/include/clang/Sema/SemaAMDGPU.h b/clang/include/clang/Sema/SemaAMDGPU.h index 969078f552c6ab7..3fdb39202610d04 100644 --- a/clang/include/clang/Sema/SemaAMDGPU.h +++ b/clang/include/clang/Sema/SemaAMDGPU.h @@ -13,14 +13,13 @@ #ifndef LLVM_CLANG_SEMA_SEMAAMDGPU_H #define LLVM_CLANG_SEMA_SEMAAMDGPU_H -#include "clang/AST/Attr.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/AttributeCommonInfo.h" -#include "clang/Sema/ParsedAttr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { +class AttributeCommonInfo; +class ParsedAttr; + class SemaAMDGPU : public SemaBase { public: SemaAMDGPU(Sema &S); diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h index fedc7df7908f17c..b8196a3170d63c6 100644 --- a/clang/include/clang/Sema/SemaARM.h +++ b/clang/include/clang/Sema/SemaARM.h @@ -13,15 +13,18 @@ #ifndef LLVM_CLANG_SEMA_SEMAARM_H #define LLVM_CLANG_SEMA_SEMAARM_H -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include +namespace llvm { +template class SmallVector; +} // namespace llvm + namespace clang { class ParsedAttr; +class TargetInfo; class SemaARM : public SemaBase { public: @@ -60,10 +63,10 @@ class SemaARM : public SemaBase { unsigned ExpectedFieldNum, bool AllowName); bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall); - bool MveAliasValid(unsigned BuiltinID, StringRef AliasName); - bool CdeAliasValid(unsigned BuiltinID, StringRef AliasName); - bool SveAliasValid(unsigned BuiltinID, StringRef AliasName); - bool SmeAliasValid(unsigned BuiltinID, StringRef AliasName); + bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName); + bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName); + bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName); + bool SmeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName); void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL); void handleNewAttr(Decl *D, const ParsedAttr &AL); void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL); diff --git a/clang/include/clang/Sema/SemaAVR.h b/clang/include/clang/Sema/SemaAVR.h index 708da3a6026acee..d89ce054b864d3e 100644 --- a/clang/include/clang/Sema/SemaAVR.h +++ b/clang/include/clang/Sema/SemaAVR.h @@ -13,10 +13,10 @@ #ifndef LLVM_CLANG_SEMA_SEMAAVR_H #define LLVM_CLANG_SEMA_SEMAAVR_H +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { -class Decl; class ParsedAttr; class SemaAVR : public SemaBase { diff --git a/clang/include/clang/Sema/SemaBPF.h b/clang/include/clang/Sema/SemaBPF.h index 0182ccfe508a7be..d7577aea7012274 100644 --- a/clang/include/clang/Sema/SemaBPF.h +++ b/clang/include/clang/Sema/SemaBPF.h @@ -13,9 +13,7 @@ #ifndef LLVM_CLANG_SEMA_SEMABPF_H #define LLVM_CLANG_SEMA_SEMABPF_H -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { diff --git a/clang/include/clang/Sema/SemaCUDA.h b/clang/include/clang/Sema/SemaCUDA.h index 63dc3f4da240b36..71f05e88fb539cf 100644 --- a/clang/include/clang/Sema/SemaCUDA.h +++ b/clang/include/clang/Sema/SemaCUDA.h @@ -13,24 +13,34 @@ #ifndef LLVM_CLANG_SEMA_SEMACUDA_H #define LLVM_CLANG_SEMA_SEMACUDA_H -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" +#include "clang/AST/ASTFwd.h" +#include "clang/AST/DeclAccessPair.h" #include "clang/AST/Redeclarable.h" #include "clang/Basic/Cuda.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Ownership.h" -#include "clang/Sema/ParsedAttr.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include +#include namespace clang { +namespace sema { +class Capture; +} // namespace sema +class ASTReader; +class ASTWriter; enum class CUDAFunctionTarget; +enum class CXXSpecialMemberKind; +class ParsedAttributesView; +class Scope; class SemaCUDA : public SemaBase { public: diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h index 6bf0f2473cbf437..50409439389b068 100644 --- a/clang/include/clang/Sema/SemaCodeCompletion.h +++ b/clang/include/clang/Sema/SemaCodeCompletion.h @@ -13,26 +13,26 @@ #ifndef LLVM_CLANG_SEMA_SEMACODECOMPLETION_H #define LLVM_CLANG_SEMA_SEMACODECOMPLETION_H -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/Type.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleLoader.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Ownership.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/StringRef.h" #include namespace clang { +class DeclGroupRef; +class MacroInfo; +class Scope; +class TemplateName; class SemaCodeCompletion : public SemaBase { public: diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index d60cb2a57d49187..3aae3383c215b55 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -13,19 +13,18 @@ #ifndef LLVM_CLANG_SEMA_SEMAHLSL_H #define LLVM_CLANG_SEMA_SEMAHLSL_H +#include "clang/AST/ASTFwd.h" #include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/AttributeCommonInfo.h" -#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" +#include "llvm/TargetParser/Triple.h" #include namespace clang { +class AttributeCommonInfo; +class IdentifierInfo; class ParsedAttr; +class Scope; class SemaHLSL : public SemaBase { public: diff --git a/clang/include/clang/Sema/SemaHexagon.h b/clang/include/clang/Sema/SemaHexagon.h index 2d4a04f824bc2ef..82e811dfc42e484 100644 --- a/clang/include/clang/Sema/SemaHexagon.h +++ b/clang/include/clang/Sema/SemaHexagon.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_SEMA_SEMAHEXAGON_H #define LLVM_CLANG_SEMA_SEMAHEXAGON_H -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { diff --git a/clang/include/clang/Sema/SemaLoongArch.h b/clang/include/clang/Sema/SemaLoongArch.h index aef0df9e8710ff0..98a7e99e31572a2 100644 --- a/clang/include/clang/Sema/SemaLoongArch.h +++ b/clang/include/clang/Sema/SemaLoongArch.h @@ -13,11 +13,12 @@ #ifndef LLVM_CLANG_SEMA_SEMALOONGARCH_H #define LLVM_CLANG_SEMA_SEMALOONGARCH_H -#include "clang/AST/Expr.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { +class TargetInfo; + class SemaLoongArch : public SemaBase { public: SemaLoongArch(Sema &S); diff --git a/clang/include/clang/Sema/SemaM68k.h b/clang/include/clang/Sema/SemaM68k.h index 5a9767d5ea52163..dece033c22030a9 100644 --- a/clang/include/clang/Sema/SemaM68k.h +++ b/clang/include/clang/Sema/SemaM68k.h @@ -13,10 +13,10 @@ #ifndef LLVM_CLANG_SEMA_SEMAM68K_H #define LLVM_CLANG_SEMA_SEMAM68K_H +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { -class Decl; class ParsedAttr; class SemaM68k : public SemaBase { diff --git a/clang/include/clang/Sema/SemaMIPS.h b/clang/include/clang/Sema/SemaMIPS.h index 6366dce57626af8..41feeb69b80594b 100644 --- a/clang/include/clang/Sema/SemaMIPS.h +++ b/clang/include/clang/Sema/SemaMIPS.h @@ -13,13 +13,12 @@ #ifndef LLVM_CLANG_SEMA_SEMAMIPS_H #define LLVM_CLANG_SEMA_SEMAMIPS_H -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { class ParsedAttr; +class TargetInfo; class SemaMIPS : public SemaBase { public: diff --git a/clang/include/clang/Sema/SemaMSP430.h b/clang/include/clang/Sema/SemaMSP430.h index e1034aefe881640..30eb8eaf6aa1a39 100644 --- a/clang/include/clang/Sema/SemaMSP430.h +++ b/clang/include/clang/Sema/SemaMSP430.h @@ -13,10 +13,10 @@ #ifndef LLVM_CLANG_SEMA_SEMAMSP430_H #define LLVM_CLANG_SEMA_SEMAMSP430_H +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { -class Decl; class ParsedAttr; class SemaMSP430 : public SemaBase { diff --git a/clang/include/clang/Sema/SemaNVPTX.h b/clang/include/clang/Sema/SemaNVPTX.h index a663c694179d98a..de47997d2f8bf16 100644 --- a/clang/include/clang/Sema/SemaNVPTX.h +++ b/clang/include/clang/Sema/SemaNVPTX.h @@ -13,11 +13,12 @@ #ifndef LLVM_CLANG_SEMA_SEMANVPTX_H #define LLVM_CLANG_SEMA_SEMANVPTX_H -#include "clang/AST/Expr.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { +class TargetInfo; + class SemaNVPTX : public SemaBase { public: SemaNVPTX(Sema &S); diff --git a/clang/include/clang/Sema/SemaObjC.h b/clang/include/clang/Sema/SemaObjC.h index 07c3c1a06be1603..213c37b5091fe0f 100644 --- a/clang/include/clang/Sema/SemaObjC.h +++ b/clang/include/clang/Sema/SemaObjC.h @@ -13,11 +13,8 @@ #ifndef LLVM_CLANG_SEMA_SEMAOBJC_H #define LLVM_CLANG_SEMA_SEMAOBJC_H -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/NSAPI.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/Type.h" @@ -27,24 +24,29 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TokenKinds.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Lookup.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Redeclaration.h" -#include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include #include -#include #include namespace clang { +class AttributeCommonInfo; +class AvailabilitySpec; enum class CheckedConversionKind; +class DeclGroupRef; +class LookupResult; +struct ObjCDictionaryElement; class ParsedAttr; +class ParsedAttributesView; +class Scope; struct SkipBodyInfo; class SemaObjC : public SemaBase { diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index a5f2a8bf7465777..0ca76842e5f9028 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -16,13 +16,19 @@ #include "clang/AST/DeclGroup.h" #include "clang/AST/StmtOpenACC.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/SemaBase.h" +#include "llvm/ADT/SmallVector.h" +#include +#include +#include #include namespace clang { +class IdentifierInfo; class OpenACCClause; class SemaOpenACC : public SemaBase { diff --git a/clang/include/clang/Sema/SemaOpenCL.h b/clang/include/clang/Sema/SemaOpenCL.h index 7d6b4b0dec09c25..04b2b617fb12fe6 100644 --- a/clang/include/clang/Sema/SemaOpenCL.h +++ b/clang/include/clang/Sema/SemaOpenCL.h @@ -13,10 +13,10 @@ #ifndef LLVM_CLANG_SEMA_SEMAOPENCL_H #define LLVM_CLANG_SEMA_SEMAOPENCL_H +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { -class Decl; class ParsedAttr; class SemaOpenCL : public SemaBase { diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index e55731212c4a41e..53191e7bb4272bb 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -14,17 +14,12 @@ #ifndef LLVM_CLANG_SEMA_SEMAOPENMP_H #define LLVM_CLANG_SEMA_SEMAOPENMP_H +#include "clang/AST/ASTFwd.h" #include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/OpenMPClause.h" -#include "clang/AST/Stmt.h" #include "clang/AST/StmtOpenMP.h" -#include "clang/AST/Type.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" @@ -32,17 +27,23 @@ #include "clang/Basic/Specifiers.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Ownership.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerUnion.h" +#include "llvm/Frontend/OpenMP/OMP.h.inc" +#include "llvm/Frontend/OpenMP/OMPConstants.h" #include #include #include namespace clang { +namespace sema { +class FunctionScopeInfo; +} // namespace sema + +class DeclContext; +class DeclGroupRef; class ParsedAttr; +class Scope; class SemaOpenMP : public SemaBase { public: diff --git a/clang/include/clang/Sema/SemaPPC.h b/clang/include/clang/Sema/SemaPPC.h index 3e8929d5b6dedab..f8edecc4fcb7bff 100644 --- a/clang/include/clang/Sema/SemaPPC.h +++ b/clang/include/clang/Sema/SemaPPC.h @@ -13,13 +13,14 @@ #ifndef LLVM_CLANG_SEMA_SEMAPPC_H #define LLVM_CLANG_SEMA_SEMAPPC_H -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaBase.h" namespace clang { +class TargetInfo; + class SemaPPC : public SemaBase { public: SemaPPC(Sema &S); diff --git a/clang/include/clang/Sema/SemaPseudoObject.h b/clang/include/clang/Sema/SemaPseudoObject.h index 22d8be2b3726ee1..4753987070b750a 100644 --- a/clang/include/clang/Sema/SemaPseudoObject.h +++ b/clang/include/clang/Sema/SemaPseudoObject.h @@ -14,14 +14,14 @@ #ifndef LLVM_CLANG_SEMA_SEMAPSEUDOOBJECT_H #define LLVM_CLANG_SEMA_SEMAPSEUDOOBJECT_H -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/OperationKinds.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Ownership.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" namespace clang { +class Scope; class SemaPseudoObject : public SemaBase { public: diff --git a/clang/include/clang/Sema/SemaRISCV.h b/clang/include/clang/Sema/SemaRISCV.h index 48d15c411bddde2..d62fca8128b2a3a 100644 --- a/clang/include/clang/Sema/SemaRISCV.h +++ b/clang/include/clang/Sema/SemaRISCV.h @@ -13,18 +13,21 @@ #ifndef LLVM_CLANG_SEMA_SEMARISCV_H #define LLVM_CLANG_SEMA_SEMARISCV_H -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include namespace clang { +namespace sema { +class RISCVIntrinsicManager; +} // namespace sema + class ParsedAttr; +class TargetInfo; class SemaRISCV : public SemaBase { public: @@ -39,7 +42,7 @@ class SemaRISCV : public SemaBase { bool isValidRVVBitcast(QualType srcType, QualType destType); void handleInterruptAttr(Decl *D, const ParsedAttr &AL); - bool isAliasValid(unsigned BuiltinID, StringRef AliasName); + bool isAliasValid(unsigned BuiltinID, llvm::StringRef AliasName); /// Indicate RISC-V vector builtin functions enabled or not. bool DeclareRVVBuiltins = false; diff --git a/clang/include/clang/Sema/SemaSYCL.h b/clang/include/clang/Sema/SemaSYCL.h index 363178546a236c5..27c42b540183073 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_SEMA_SEMASYCL_H #define LLVM_CLANG_SEMA_SEMASYCL_H -#include "clang/AST/Decl.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Ownership.h" diff --git a/clang/include/clang/Sema/SemaSwift.h b/clang/include/clang/Sema/SemaSwift.h index a5561d756affd10..8d8f1467054ac5b 100644 --- a/clang/include/clang/Sema/SemaSwift.h +++ b/clang/include/clang/Sema/SemaSwift.h @@ -13,15 +13,15 @@ #ifndef LLVM_CLANG_SEMA_SEMASWIFT_H #define LLVM_CLANG_SEMA_SEMASWIFT_H -#include "clang/AST/Attr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/SemaBase.h" -#include "llvm/ADT/StringRef.h" namespace clang { class AttributeCommonInfo; class Decl; +enum class ParameterABI; class ParsedAttr; class SwiftNameAttr; diff --git a/clang/include/clang/Sema/SemaSystemZ.h b/clang/include/clang/Sema/SemaSystemZ.h index 8945471d53d638f..1a3e29f7a9312a6 100644 --- a/clang/include/clang/Sema/SemaSystemZ.h +++ b/clang/include/clang/Sema/SemaSystemZ.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_SEMA_SEMASYSTEMZ_H #define LLVM_CLANG_SEMA_SEMASYSTEMZ_H -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { diff --git a/clang/include/clang/Sema/SemaWasm.h b/clang/include/clang/Sema/SemaWasm.h index c3c781535024aef..8841fdff2303538 100644 --- a/clang/include/clang/Sema/SemaWasm.h +++ b/clang/include/clang/Sema/SemaWasm.h @@ -13,14 +13,13 @@ #ifndef LLVM_CLANG_SEMA_SEMAWASM_H #define LLVM_CLANG_SEMA_SEMAWASM_H -#include "clang/AST/Attr.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Sema/ParsedAttr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Sema/SemaBase.h" namespace clang { +class ParsedAttr; +class TargetInfo; + class SemaWasm : public SemaBase { public: SemaWasm(Sema &S); diff --git a/clang/include/clang/Sema/SemaX86.h b/clang/include/clang/Sema/SemaX86.h index e53aaf229c38dda..b5a23f1bede047e 100644 --- a/clang/include/clang/Sema/SemaX86.h +++ b/clang/include/clang/Sema/SemaX86.h @@ -13,14 +13,13 @@ #ifndef LLVM_CLANG_SEMA_SEMAX86_H #define LLVM_CLANG_SEMA_SEMAX86_H -#include "clang/AST/DeclBase.h" -#include "clang/AST/Expr.h" +#include "clang/AST/ASTFwd.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaBase.h" namespace clang { class ParsedAttr; +class TargetInfo; class SemaX86 : public SemaBase { public: diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index fba5f4e8907dae8..d724a9ea471b54a 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0; /// API notes file minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t VERSION_MINOR = 29; // SwiftConformsTo +const uint16_t VERSION_MINOR = 30; // fields const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; @@ -72,6 +72,10 @@ enum BlockID { /// used in other tables. OBJC_SELECTOR_BLOCK_ID, + /// The fields data block, which maps names fields of C records to + /// information about the field. + FIELD_BLOCK_ID, + /// The global variables data block, which maps global variable names to /// information about the global variable. GLOBAL_VARIABLE_BLOCK_ID, @@ -199,6 +203,20 @@ using CXXMethodDataLayout = >; } // namespace cxx_method_block +namespace field_block { +enum { + FIELD_DATA = 1, +}; + +using FieldDataLayout = + llvm::BCRecordLayout, // table offset within the blob (see + // below) + llvm::BCBlob // map from C (context id, name) + // tuples to C field information + >; +} // namespace field_block + namespace objc_selector_block { enum { OBJC_SELECTOR_DATA = 1, diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index c05fdffe4a071b8..da8a86f7adb16e0 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -299,6 +299,28 @@ class ObjCPropertyTableInfo } }; +/// Used to deserialize the on-disk C record field table. +class FieldTableInfo + : public VersionedTableInfo { +public: + static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { + auto CtxID = endian::readNext(Data); + auto NameID = endian::readNext(Data); + return {CtxID, NameID}; + } + + hash_value_type ComputeHash(internal_key_type Key) { + return static_cast(Key.hashValue()); + } + + static FieldInfo readUnversioned(internal_key_type Key, + const uint8_t *&Data) { + FieldInfo Info; + ReadVariableInfo(Data, Info); + return Info; + } +}; + /// Read serialized ParamInfo. void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) { ReadVariableInfo(Data, Info); @@ -653,6 +675,12 @@ class APINotesReader::Implementation { /// The Objective-C property table. std::unique_ptr ObjCPropertyTable; + using SerializedFieldTable = + llvm::OnDiskIterableChainedHashTable; + + /// The C record field table. + std::unique_ptr FieldTable; + using SerializedObjCMethodTable = llvm::OnDiskIterableChainedHashTable; @@ -720,6 +748,8 @@ class APINotesReader::Implementation { llvm::SmallVectorImpl &Scratch); bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl &Scratch); + bool readFieldBlock(llvm::BitstreamCursor &Cursor, + llvm::SmallVectorImpl &Scratch); bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl &Scratch); bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor, @@ -1252,6 +1282,81 @@ bool APINotesReader::Implementation::readCXXMethodBlock( return false; } +bool APINotesReader::Implementation::readFieldBlock( + llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl &Scratch) { + if (Cursor.EnterSubBlock(FIELD_BLOCK_ID)) + return true; + + llvm::Expected MaybeNext = Cursor.advance(); + if (!MaybeNext) { + // FIXME this drops the error on the floor. + consumeError(MaybeNext.takeError()); + return false; + } + llvm::BitstreamEntry Next = MaybeNext.get(); + while (Next.Kind != llvm::BitstreamEntry::EndBlock) { + if (Next.Kind == llvm::BitstreamEntry::Error) + return true; + + if (Next.Kind == llvm::BitstreamEntry::SubBlock) { + // Unknown sub-block, possibly for use by a future version of the + // API notes format. + if (Cursor.SkipBlock()) + return true; + + MaybeNext = Cursor.advance(); + if (!MaybeNext) { + // FIXME this drops the error on the floor. + consumeError(MaybeNext.takeError()); + return false; + } + Next = MaybeNext.get(); + continue; + } + + Scratch.clear(); + llvm::StringRef BlobData; + llvm::Expected MaybeKind = + Cursor.readRecord(Next.ID, Scratch, &BlobData); + if (!MaybeKind) { + // FIXME this drops the error on the floor. + consumeError(MaybeKind.takeError()); + return false; + } + unsigned Kind = MaybeKind.get(); + switch (Kind) { + case field_block::FIELD_DATA: { + // Already saw field table. + if (FieldTable) + return true; + + uint32_t tableOffset; + field_block::FieldDataLayout::readRecord(Scratch, tableOffset); + auto base = reinterpret_cast(BlobData.data()); + + FieldTable.reset(SerializedFieldTable::Create( + base + tableOffset, base + sizeof(uint32_t), base)); + break; + } + + default: + // Unknown record, possibly for use by a future version of the + // module format. + break; + } + + MaybeNext = Cursor.advance(); + if (!MaybeNext) { + // FIXME this drops the error on the floor. + consumeError(MaybeNext.takeError()); + return false; + } + Next = MaybeNext.get(); + } + + return false; +} + bool APINotesReader::Implementation::readObjCSelectorBlock( llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl &Scratch) { if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID)) @@ -1812,6 +1917,14 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer, } break; + case FIELD_BLOCK_ID: + if (!HasValidControlBlock || + Implementation->readFieldBlock(Cursor, Scratch)) { + Failed = true; + return; + } + break; + case OBJC_SELECTOR_BLOCK_ID: if (!HasValidControlBlock || Implementation->readObjCSelectorBlock(Cursor, Scratch)) { @@ -2031,6 +2144,23 @@ auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, return {Implementation->SwiftVersion, *Known}; } +auto APINotesReader::lookupField(ContextID CtxID, llvm::StringRef Name) + -> VersionedInfo { + if (!Implementation->FieldTable) + return std::nullopt; + + std::optional NameID = Implementation->getIdentifier(Name); + if (!NameID) + return std::nullopt; + + auto Known = Implementation->FieldTable->find( + SingleDeclTableKey(CtxID.Value, *NameID)); + if (Known == Implementation->FieldTable->end()) + return std::nullopt; + + return {Implementation->SwiftVersion, *Known}; +} + auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name) -> VersionedInfo { if (!Implementation->CXXMethodTable) diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index cf3a0bee393eee4..c452677983bb360 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -62,6 +62,13 @@ class APINotesWriter::Implementation { llvm::SmallVector, 1>> ObjCProperties; + /// Information about C record fields. + /// + /// Indexed by the context ID and name ID. + llvm::DenseMap, 1>> + Fields; + /// Information about Objective-C methods. /// /// Indexed by the context ID, selector ID, and Boolean (stored as a char) @@ -158,6 +165,7 @@ class APINotesWriter::Implementation { void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream); void writeObjCMethodBlock(llvm::BitstreamWriter &Stream); void writeCXXMethodBlock(llvm::BitstreamWriter &Stream); + void writeFieldBlock(llvm::BitstreamWriter &Stream); void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream); void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream); void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream); @@ -190,6 +198,7 @@ void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) { writeObjCPropertyBlock(Stream); writeObjCMethodBlock(Stream); writeCXXMethodBlock(Stream); + writeFieldBlock(Stream); writeObjCSelectorBlock(Stream); writeGlobalVariableBlock(Stream); writeGlobalFunctionBlock(Stream); @@ -858,6 +867,62 @@ void APINotesWriter::Implementation::writeCXXMethodBlock( } } +namespace { +/// Used to serialize the on-disk C field table. +class FieldTableInfo + : public VersionedTableInfo { +public: + unsigned getKeyLength(key_type_ref) { + return sizeof(uint32_t) + sizeof(uint32_t); + } + + void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { + llvm::support::endian::Writer writer(OS, llvm::endianness::little); + writer.write(Key.parentContextID); + writer.write(Key.nameID); + } + + hash_value_type ComputeHash(key_type_ref key) { + return static_cast(key.hashValue()); + } + + unsigned getUnversionedInfoSize(const FieldInfo &FI) { + return getVariableInfoSize(FI); + } + + void emitUnversionedInfo(raw_ostream &OS, const FieldInfo &FI) { + emitVariableInfo(OS, FI); + } +}; +} // namespace + +void APINotesWriter::Implementation::writeFieldBlock( + llvm::BitstreamWriter &Stream) { + llvm::BCBlockRAII Scope(Stream, FIELD_BLOCK_ID, 3); + + if (Fields.empty()) + return; + + { + llvm::SmallString<4096> HashTableBlob; + uint32_t Offset; + { + llvm::OnDiskChainedHashTableGenerator Generator; + for (auto &FD : Fields) + Generator.insert(FD.first, FD.second); + + llvm::raw_svector_ostream BlobStream(HashTableBlob); + // Make sure that no bucket is at offset 0 + llvm::support::endian::write(BlobStream, 0, + llvm::endianness::little); + Offset = Generator.Emit(BlobStream); + } + + field_block::FieldDataLayout FieldData(Stream); + FieldData.emit(Scratch, Offset, HashTableBlob); + } +} + namespace { /// Used to serialize the on-disk Objective-C selector table. class ObjCSelectorTableInfo { @@ -1423,6 +1488,14 @@ void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name, Implementation->CXXMethods[Key].push_back({SwiftVersion, Info}); } +void APINotesWriter::addField(ContextID CtxID, llvm::StringRef Name, + const FieldInfo &Info, + VersionTuple SwiftVersion) { + IdentifierID NameID = Implementation->getIdentifier(Name); + SingleDeclTableKey Key(CtxID.Value, NameID); + Implementation->Fields[Key].push_back({SwiftVersion, Info}); +} + void APINotesWriter::addGlobalVariable(std::optional Ctx, llvm::StringRef Name, const GlobalVariableInfo &Info, diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 2205686c4d15c3f..16fd59244086fd4 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -405,6 +405,38 @@ template <> struct ScalarEnumerationTraits { } // namespace yaml } // namespace llvm +namespace { +struct Field { + StringRef Name; + std::optional Nullability; + AvailabilityItem Availability; + std::optional SwiftPrivate; + StringRef SwiftName; + StringRef Type; +}; + +typedef std::vector FieldsSeq; +} // namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(Field) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, Field &F) { + IO.mapRequired("Name", F.Name); + IO.mapOptional("Nullability", F.Nullability, std::nullopt); + IO.mapOptional("Availability", F.Availability.Mode, + APIAvailability::Available); + IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef("")); + IO.mapOptional("SwiftPrivate", F.SwiftPrivate); + IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); + IO.mapOptional("Type", F.Type, StringRef("")); + } +}; +} // namespace yaml +} // namespace llvm + namespace { struct Tag; typedef std::vector TagsSeq; @@ -425,6 +457,7 @@ struct Tag { std::optional EnumConvenienceKind; std::optional SwiftCopyable; FunctionsSeq Methods; + FieldsSeq Fields; /// Tags that are declared within the current tag. Only the tags that have /// corresponding API Notes will be listed. @@ -463,6 +496,7 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); + IO.mapOptional("Fields", T.Fields); IO.mapOptional("Tags", T.Tags); } }; @@ -793,6 +827,16 @@ class YAMLConverter { SwiftVersion); } + template + void convertVariable(const T &Entity, VariableInfo &VI) { + convertAvailability(Entity.Availability, VI, Entity.Name); + VI.setSwiftPrivate(Entity.SwiftPrivate); + VI.SwiftName = std::string(Entity.SwiftName); + if (Entity.Nullability) + VI.setNullabilityAudited(*Entity.Nullability); + VI.setType(std::string(Entity.Type)); + } + void convertContext(std::optional ParentContextID, const Class &C, ContextKind Kind, VersionTuple SwiftVersion) { // Write the class. @@ -848,14 +892,9 @@ class YAMLConverter { // Translate from Property into ObjCPropertyInfo. ObjCPropertyInfo PI; - convertAvailability(Property.Availability, PI, Property.Name); - PI.setSwiftPrivate(Property.SwiftPrivate); - PI.SwiftName = std::string(Property.SwiftName); - if (Property.Nullability) - PI.setNullabilityAudited(*Property.Nullability); + convertVariable(Property, PI); if (Property.SwiftImportAsAccessors) PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors); - PI.setType(std::string(Property.Type)); // Add both instance and class properties with this name. if (Property.Kind) { @@ -970,6 +1009,12 @@ class YAMLConverter { CI, SwiftVersion); Context TagCtx(TagCtxID, ContextKind::Tag); + for (const auto &Field : T.Fields) { + FieldInfo FI; + convertVariable(Field, FI); + Writer.addField(TagCtxID, Field.Name, FI, SwiftVersion); + } + for (const auto &CXXMethod : T.Methods) { CXXMethodInfo MI; convertFunction(CXXMethod, MI); @@ -1037,12 +1082,7 @@ class YAMLConverter { } GlobalVariableInfo GVI; - convertAvailability(Global.Availability, GVI, Global.Name); - GVI.setSwiftPrivate(Global.SwiftPrivate); - GVI.SwiftName = std::string(Global.SwiftName); - if (Global.Nullability) - GVI.setNullabilityAudited(*Global.Nullability); - GVI.setType(std::string(Global.Type)); + convertVariable(Global, GVI); Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion); } diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index 5835559bff6b720..1a8a200f2fc1949 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -596,7 +596,7 @@ bool MigrationProcess::applyTransform(TransformFn trans, for (Rewriter::buffer_iterator I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { FileID FID = I->first; - RewriteBuffer &buf = I->second; + llvm::RewriteBuffer &buf = I->second; OptionalFileEntryRef file = Ctx.getSourceManager().getFileEntryRefForID(FID); assert(file); diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index 4357c8e3f09a550..c1bc7c762088f29 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -36,6 +36,7 @@ using namespace clang; using namespace arcmt; using namespace ento; +using llvm::RewriteBuffer; namespace { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0dbbe0043f70317..b201d201e1ea6ad 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "ByteCode/Context.h" #include "CXXABI.h" -#include "Interp/Context.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConcept.h" #include "clang/AST/ASTMutationListener.h" @@ -3279,7 +3279,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, case Type::MemberPointer: { OS << "M"; - const auto *MPT = T->getAs(); + const auto *MPT = T->castAs(); encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0)); encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType()); return; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 198bc34a9f031bb..3bc0a647ebf94ff 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -4429,11 +4429,14 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { auto FriendLocOrErr = import(D->getFriendLoc()); if (!FriendLocOrErr) return FriendLocOrErr.takeError(); + auto EllipsisLocOrErr = import(D->getEllipsisLoc()); + if (!EllipsisLocOrErr) + return EllipsisLocOrErr.takeError(); FriendDecl *FrD; if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, - *LocationOrErr, ToFU, - *FriendLocOrErr, ToTPLists)) + *LocationOrErr, ToFU, *FriendLocOrErr, + *EllipsisLocOrErr, ToTPLists)) return FrD; FrD->setAccess(D->getAccess()); diff --git a/clang/lib/AST/Availability.cpp b/clang/lib/AST/Availability.cpp index 238359a2dedfcf4..cf040fc727d11f4 100644 --- a/clang/lib/AST/Availability.cpp +++ b/clang/lib/AST/Availability.cpp @@ -16,33 +16,104 @@ #include "clang/AST/Decl.h" #include "clang/Basic/TargetInfo.h" -namespace clang { +namespace { + +/// Represents the availability of a symbol across platforms. +struct AvailabilitySet { + bool UnconditionallyDeprecated = false; + bool UnconditionallyUnavailable = false; + + void insert(clang::AvailabilityInfo &&Availability) { + auto *Found = getForPlatform(Availability.Domain); + if (Found) + Found->mergeWith(std::move(Availability)); + else + Availabilities.emplace_back(std::move(Availability)); + } + + clang::AvailabilityInfo *getForPlatform(llvm::StringRef Domain) { + auto *It = llvm::find_if(Availabilities, + [Domain](const clang::AvailabilityInfo &Info) { + return Domain.compare(Info.Domain) == 0; + }); + return It == Availabilities.end() ? nullptr : It; + } -AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) { - ASTContext &Context = Decl->getASTContext(); - StringRef PlatformName = Context.getTargetInfo().getPlatformName(); - AvailabilityInfo Availability; +private: + llvm::SmallVector Availabilities; +}; +static void createInfoForDecl(const clang::Decl *Decl, + AvailabilitySet &Availabilities) { // Collect availability attributes from all redeclarations. for (const auto *RD : Decl->redecls()) { - for (const auto *A : RD->specific_attrs()) { - if (A->getPlatform()->getName() != PlatformName) - continue; - Availability = AvailabilityInfo( + for (const auto *A : RD->specific_attrs()) { + Availabilities.insert(clang::AvailabilityInfo( A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(), - A->getObsoleted(), A->getUnavailable(), false, false); - break; + A->getObsoleted(), A->getUnavailable(), false, false)); } - if (const auto *A = RD->getAttr()) + if (const auto *A = RD->getAttr()) if (!A->isImplicit()) - Availability.UnconditionallyUnavailable = true; + Availabilities.UnconditionallyUnavailable = true; - if (const auto *A = RD->getAttr()) + if (const auto *A = RD->getAttr()) if (!A->isImplicit()) - Availability.UnconditionallyDeprecated = true; + Availabilities.UnconditionallyDeprecated = true; } - return Availability; +} + +} // namespace + +namespace clang { + +void AvailabilityInfo::mergeWith(AvailabilityInfo Other) { + if (isDefault() && Other.isDefault()) + return; + + if (Domain.empty()) + Domain = Other.Domain; + + UnconditionallyUnavailable |= Other.UnconditionallyUnavailable; + UnconditionallyDeprecated |= Other.UnconditionallyDeprecated; + Unavailable |= Other.Unavailable; + + Introduced = std::max(Introduced, Other.Introduced); + + // Default VersionTuple is 0.0.0 so if both are non default let's pick the + // smallest version number, otherwise select the one that is non-zero if there + // is one. + if (!Deprecated.empty() && !Other.Deprecated.empty()) + Deprecated = std::min(Deprecated, Other.Deprecated); + else + Deprecated = std::max(Deprecated, Other.Deprecated); + + if (!Obsoleted.empty() && !Other.Obsoleted.empty()) + Obsoleted = std::min(Obsoleted, Other.Obsoleted); + else + Obsoleted = std::max(Obsoleted, Other.Obsoleted); +} + +AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *D) { + AvailabilitySet Availabilities; + // Walk DeclContexts upwards starting from D to find the combined availability + // of the symbol. + for (const auto *Ctx = D; Ctx; + Ctx = llvm::cast_or_null(Ctx->getDeclContext())) + createInfoForDecl(Ctx, Availabilities); + + if (auto *Avail = Availabilities.getForPlatform( + D->getASTContext().getTargetInfo().getPlatformName())) { + Avail->UnconditionallyDeprecated = Availabilities.UnconditionallyDeprecated; + Avail->UnconditionallyUnavailable = + Availabilities.UnconditionallyUnavailable; + return std::move(*Avail); + } + + AvailabilityInfo Avail; + Avail.UnconditionallyDeprecated = Availabilities.UnconditionallyDeprecated; + Avail.UnconditionallyUnavailable = Availabilities.UnconditionallyUnavailable; + return Avail; } } // namespace clang diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/ByteCode/Boolean.h similarity index 95% rename from clang/lib/AST/Interp/Boolean.h rename to clang/lib/AST/ByteCode/Boolean.h index 23f728603676464..f1914ddb9970dc5 100644 --- a/clang/lib/AST/Interp/Boolean.h +++ b/clang/lib/AST/ByteCode/Boolean.h @@ -9,25 +9,25 @@ #ifndef LLVM_CLANG_AST_INTERP_BOOLEAN_H #define LLVM_CLANG_AST_INTERP_BOOLEAN_H -#include -#include #include "Integral.h" #include "clang/AST/APValue.h" #include "clang/AST/ComparisonCategories.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include +#include namespace clang { namespace interp { /// Wrapper around boolean types. class Boolean final { - private: +private: /// Underlying boolean. bool V; - public: +public: /// Zero-initializes a boolean. Boolean() : V(false) {} explicit Boolean(bool V) : V(V) {} @@ -44,6 +44,7 @@ class Boolean final { Boolean operator-() const { return Boolean(V); } Boolean operator-(const Boolean &Other) const { return Boolean(V - Other.V); } Boolean operator~() const { return Boolean(true); } + Boolean operator!() const { return Boolean(!V); } template >> explicit operator Ty() const { @@ -104,8 +105,7 @@ class Boolean final { static Boolean zero() { return from(false); } - template - static Boolean from(T Value, unsigned NumBits) { + template static Boolean from(T Value, unsigned NumBits) { return Boolean(Value); } @@ -153,7 +153,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Boolean &B) { return OS; } -} // namespace interp -} // namespace clang +} // namespace interp +} // namespace clang #endif diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp similarity index 86% rename from clang/lib/AST/Interp/ByteCodeEmitter.cpp rename to clang/lib/AST/ByteCode/ByteCodeEmitter.cpp index a01fa15dc0b7dc9..35ae1547939fdd5 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp @@ -195,6 +195,48 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { return Func; } +/// Compile an ObjC block, i.e. ^(){}, that thing. +/// +/// FIXME: We do not support calling the block though, so we create a function +/// here but do not compile any code for it. +Function *ByteCodeEmitter::compileObjCBlock(const BlockExpr *BE) { + const BlockDecl *BD = BE->getBlockDecl(); + // Set up argument indices. + unsigned ParamOffset = 0; + SmallVector ParamTypes; + SmallVector ParamOffsets; + llvm::DenseMap ParamDescriptors; + + // Assign descriptors to all parameters. + // Composite objects are lowered to pointers. + for (const ParmVarDecl *PD : BD->parameters()) { + std::optional T = Ctx.classify(PD->getType()); + PrimType PT = T.value_or(PT_Ptr); + Descriptor *Desc = P.createDescriptor(PD, PT); + ParamDescriptors.insert({ParamOffset, {PT, Desc}}); + Params.insert({PD, {ParamOffset, T != std::nullopt}}); + ParamOffsets.push_back(ParamOffset); + ParamOffset += align(primSize(PT)); + ParamTypes.push_back(PT); + } + + if (BD->hasCaptures()) + return nullptr; + + // Create a handle over the emitted code. + Function *Func = + P.createFunction(BE, ParamOffset, std::move(ParamTypes), + std::move(ParamDescriptors), std::move(ParamOffsets), + /*HasThisPointer=*/false, /*HasRVO=*/false, + /*IsUnevaluatedBuiltin=*/false); + + assert(Func); + Func->setDefined(true); + // We don't compile the BlockDecl code at all right now. + Func->setIsFullyCompiled(true); + return Func; +} + Scope::Local ByteCodeEmitter::createLocal(Descriptor *D) { NextLocalOffset += sizeof(Block); unsigned Location = NextLocalOffset; @@ -206,8 +248,7 @@ void ByteCodeEmitter::emitLabel(LabelTy Label) { const size_t Target = Code.size(); LabelOffsets.insert({Label, Target}); - if (auto It = LabelRelocs.find(Label); - It != LabelRelocs.end()) { + if (auto It = LabelRelocs.find(Label); It != LabelRelocs.end()) { for (unsigned Reloc : It->second) { using namespace llvm::support; @@ -228,8 +269,7 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) { assert(aligned(Position)); // If target is known, compute jump offset. - if (auto It = LabelOffsets.find(Label); - It != LabelOffsets.end()) + if (auto It = LabelOffsets.find(Label); It != LabelOffsets.end()) return It->second - Position; // Otherwise, record relocation and return dummy offset. @@ -308,7 +348,8 @@ void emit(Program &P, std::vector &Code, const IntegralAP &Val, } template -bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &SI) { +bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args, + const SourceInfo &SI) { bool Success = true; // The opcode is followed by arguments. The source info is diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.h b/clang/lib/AST/ByteCode/ByteCodeEmitter.h similarity index 96% rename from clang/lib/AST/Interp/ByteCodeEmitter.h rename to clang/lib/AST/ByteCode/ByteCodeEmitter.h index a19a25c2f9e8ecc..7cbbe651699b34b 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.h +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h @@ -32,6 +32,7 @@ class ByteCodeEmitter { public: /// Compiles the function into the module. Function *compileFunc(const FunctionDecl *FuncDecl); + Function *compileObjCBlock(const BlockExpr *BE); protected: ByteCodeEmitter(Context &Ctx, Program &P) : Ctx(Ctx), P(P) {} @@ -92,7 +93,7 @@ class ByteCodeEmitter { /// Emits an opcode. template - bool emitOp(Opcode Op, const Tys &... Args, const SourceInfo &L); + bool emitOp(Opcode Op, const Tys &...Args, const SourceInfo &L); protected: #define GET_LINK_PROTO diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp similarity index 99% rename from clang/lib/AST/Interp/Compiler.cpp rename to clang/lib/AST/ByteCode/Compiler.cpp index d32b595f9f07240..131b83ae8eb3976 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -327,6 +327,8 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { case CK_NullToPointer: case CK_NullToMemberPointer: { + if (!this->discard(SubExpr)) + return false; if (DiscardResult) return true; @@ -389,8 +391,6 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { return this->emitPop(T, CE); QualType PtrType = CE->getType(); - assert(PtrType->isPointerType()); - const Descriptor *Desc; if (std::optional T = classify(PtrType->getPointeeType())) Desc = P.createDescriptor(SubExpr, *T); @@ -533,10 +533,8 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { // We're creating a complex value here, so we need to // allocate storage for it. if (!Initializing) { - std::optional LocalIndex = allocateLocal(CE); - if (!LocalIndex) - return false; - if (!this->emitGetPtrLocal(*LocalIndex, CE)) + unsigned LocalIndex = allocateTemporary(CE); + if (!this->emitGetPtrLocal(LocalIndex, CE)) return false; } @@ -671,10 +669,8 @@ bool Compiler::VisitImaginaryLiteral(const ImaginaryLiteral *E) { return true; if (!Initializing) { - std::optional LocalIndex = allocateLocal(E); - if (!LocalIndex) - return false; - if (!this->emitGetPtrLocal(*LocalIndex, E)) + unsigned LocalIndex = allocateTemporary(E); + if (!this->emitGetPtrLocal(LocalIndex, E)) return false; } @@ -986,10 +982,8 @@ template bool Compiler::VisitComplexBinOp(const BinaryOperator *E) { // Prepare storage for result. if (!Initializing) { - std::optional LocalIndex = allocateLocal(E); - if (!LocalIndex) - return false; - if (!this->emitGetPtrLocal(*LocalIndex, E)) + unsigned LocalIndex = allocateTemporary(E); + if (!this->emitGetPtrLocal(LocalIndex, E)) return false; } @@ -1045,10 +1039,7 @@ bool Compiler::VisitComplexBinOp(const BinaryOperator *E) { if (!LHSIsComplex) { // This is using the RHS type for the fake-complex LHS. - if (auto LHSO = allocateLocal(RHS)) - LHSOffset = *LHSO; - else - return false; + LHSOffset = allocateTemporary(RHS); if (!this->emitGetPtrLocal(LHSOffset, E)) return false; @@ -1881,15 +1872,26 @@ bool Compiler::VisitAbstractConditionalOperator( if (!this->jumpFalse(LabelFalse)) return false; - if (!this->delegate(TrueExpr)) - return false; + { + LocalScope S(this); + if (!this->delegate(TrueExpr)) + return false; + if (!S.destroyLocals()) + return false; + } + if (!this->jump(LabelEnd)) return false; this->emitLabel(LabelFalse); - if (!this->delegate(FalseExpr)) - return false; + { + LocalScope S(this); + if (!this->delegate(FalseExpr)) + return false; + if (!S.destroyLocals()) + return false; + } this->fallthrough(LabelEnd); this->emitLabel(LabelEnd); @@ -2238,8 +2240,6 @@ bool Compiler::VisitExprWithCleanups(const ExprWithCleanups *E) { LocalScope ES(this); const Expr *SubExpr = E->getSubExpr(); - assert(E->getNumObjects() == 0 && "TODO: Implement cleanups"); - return this->delegate(SubExpr) && ES.destroyLocals(E); } @@ -2909,6 +2909,17 @@ bool Compiler::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { return this->emitFree(E->isArrayForm(), E); } +template +bool Compiler::VisitBlockExpr(const BlockExpr *E) { + const Function *Func = nullptr; + if (auto F = Compiler(Ctx, P).compileObjCBlock(E)) + Func = F; + + if (!Func) + return false; + return this->emitGetFnPtr(Func, E); +} + template bool Compiler::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { assert(Ctx.getLangOpts().CPlusPlus); @@ -3549,6 +3560,27 @@ Compiler::allocateLocal(DeclTy &&Src, const ValueDecl *ExtendingDecl) { return Local.Offset; } +template +unsigned Compiler::allocateTemporary(const Expr *E) { + QualType Ty = E->getType(); + assert(!Ty->isRecordType()); + + Descriptor *D = P.createDescriptor( + E, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(), + /*IsTemporary=*/true, /*IsMutable=*/false, /*Init=*/nullptr); + assert(D); + + Scope::Local Local = this->createLocal(D); + VariableScope *S = VarScope; + assert(S); + // Attach to topmost scope. + while (S->getParent()) + S = S->getParent(); + assert(S && !S->getParent()); + S->addLocal(Local); + return Local.Offset; +} + template const RecordType *Compiler::getRecordTy(QualType Ty) { if (const PointerType *PT = dyn_cast(Ty)) @@ -3699,7 +3731,8 @@ bool Compiler::visitDeclAndReturn(const VarDecl *VD, } template -VarCreationState Compiler::visitVarDecl(const VarDecl *VD, bool Toplevel) { +VarCreationState Compiler::visitVarDecl(const VarDecl *VD, + bool Toplevel) { // We don't know what to do with these, so just return false. if (VD->getType().isNull()) return false; @@ -5088,7 +5121,7 @@ bool Compiler::VisitUnaryOperator(const UnaryOperator *E) { if (!this->visitBool(SubExpr)) return false; - if (!this->emitInvBool(E)) + if (!this->emitInv(E)) return false; if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool) @@ -5101,7 +5134,7 @@ bool Compiler::VisitUnaryOperator(const UnaryOperator *E) { if (!this->visit(SubExpr)) return false; return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E); - case UO_Plus: // +x + case UO_Plus: // +x if (!T) return this->emitError(E); @@ -5207,7 +5240,7 @@ bool Compiler::VisitComplexUnaryOperator(const UnaryOperator *E) { return false; if (!this->emitComplexBoolCast(SubExpr)) return false; - if (!this->emitInvBool(E)) + if (!this->emitInv(E)) return false; if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool) return this->emitCast(PT_Bool, ET, E); diff --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h similarity index 99% rename from clang/lib/AST/Interp/Compiler.h rename to clang/lib/AST/ByteCode/Compiler.h index 112219c49e8bddb..5acfe3c41796c45 100644 --- a/clang/lib/AST/Interp/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -199,6 +199,7 @@ class Compiler : public ConstStmtVisitor, bool>, bool VisitStmtExpr(const StmtExpr *E); bool VisitCXXNewExpr(const CXXNewExpr *E); bool VisitCXXDeleteExpr(const CXXDeleteExpr *E); + bool VisitBlockExpr(const BlockExpr *E); // Statements. bool visitCompoundStmt(const CompoundStmt *S); @@ -297,6 +298,7 @@ class Compiler : public ConstStmtVisitor, bool>, /// Allocates a space storing a local given its type. std::optional allocateLocal(DeclTy &&Decl, const ValueDecl *ExtendingDecl = nullptr); + unsigned allocateTemporary(const Expr *E); private: friend class VariableScope; diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp similarity index 98% rename from clang/lib/AST/Interp/Context.cpp rename to clang/lib/AST/ByteCode/Context.cpp index 92ac28137fdb45d..e682d87b703ad77 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -160,6 +160,9 @@ std::optional Context::classify(QualType T) const { return PT_Uint16; case 8: return PT_Uint8; + case 1: + // Might happen for enum types. + return PT_Bool; default: return PT_IntAP; } @@ -176,7 +179,7 @@ std::optional Context::classify(QualType T) const { return PT_MemberPtr; if (T->isFunctionPointerType() || T->isFunctionReferenceType() || - T->isFunctionType()) + T->isFunctionType() || T->isBlockPointerType()) return PT_FnPtr; if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) diff --git a/clang/lib/AST/Interp/Context.h b/clang/lib/AST/ByteCode/Context.h similarity index 100% rename from clang/lib/AST/Interp/Context.h rename to clang/lib/AST/ByteCode/Context.h diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp similarity index 98% rename from clang/lib/AST/Interp/Descriptor.cpp rename to clang/lib/AST/ByteCode/Descriptor.cpp index 1b7d9f03f8ef0d0..47b8885c9ae3796 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/ByteCode/Descriptor.cpp @@ -284,6 +284,14 @@ static BlockDtorFn getDtorPrim(PrimType Type) { } static BlockMoveFn getMovePrim(PrimType Type) { + if (Type == PT_Float) + return moveTy::T>; + if (Type == PT_IntAP) + return moveTy::T>; + if (Type == PT_IntAPS) + return moveTy::T>; + if (Type == PT_MemberPtr) + return moveTy::T>; COMPOSITE_TYPE_SWITCH(Type, return moveTy, return nullptr); } diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h similarity index 99% rename from clang/lib/AST/Interp/Descriptor.h rename to clang/lib/AST/ByteCode/Descriptor.h index 6f1adeb898c4307..41899c3bd6831a2 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -229,7 +229,7 @@ struct Descriptor final { /// Returns the allocated size, including metadata. unsigned getAllocSize() const { return AllocSize; } /// returns the size of an element when the structure is viewed as an array. - unsigned getElemSize() const { return ElemSize; } + unsigned getElemSize() const { return ElemSize; } /// Returns the size of the metadata. unsigned getMetadataSize() const { return MDSize; } diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp similarity index 100% rename from clang/lib/AST/Interp/Disasm.cpp rename to clang/lib/AST/ByteCode/Disasm.cpp diff --git a/clang/lib/AST/Interp/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp similarity index 100% rename from clang/lib/AST/Interp/DynamicAllocator.cpp rename to clang/lib/AST/ByteCode/DynamicAllocator.cpp diff --git a/clang/lib/AST/Interp/DynamicAllocator.h b/clang/lib/AST/ByteCode/DynamicAllocator.h similarity index 100% rename from clang/lib/AST/Interp/DynamicAllocator.h rename to clang/lib/AST/ByteCode/DynamicAllocator.h diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp similarity index 99% rename from clang/lib/AST/Interp/EvalEmitter.cpp rename to clang/lib/AST/ByteCode/EvalEmitter.cpp index 08536536ac3c2eb..e36d86c814e17fd 100644 --- a/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp @@ -76,9 +76,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, return std::move(this->EvalResult); } -void EvalEmitter::emitLabel(LabelTy Label) { - CurrentLabel = Label; -} +void EvalEmitter::emitLabel(LabelTy Label) { CurrentLabel = Label; } EvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; } diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h similarity index 100% rename from clang/lib/AST/Interp/EvalEmitter.h rename to clang/lib/AST/ByteCode/EvalEmitter.h diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp similarity index 100% rename from clang/lib/AST/Interp/EvaluationResult.cpp rename to clang/lib/AST/ByteCode/EvaluationResult.cpp diff --git a/clang/lib/AST/Interp/EvaluationResult.h b/clang/lib/AST/ByteCode/EvaluationResult.h similarity index 100% rename from clang/lib/AST/Interp/EvaluationResult.h rename to clang/lib/AST/ByteCode/EvaluationResult.h diff --git a/clang/lib/AST/Interp/Floating.cpp b/clang/lib/AST/ByteCode/Floating.cpp similarity index 100% rename from clang/lib/AST/Interp/Floating.cpp rename to clang/lib/AST/ByteCode/Floating.cpp diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/ByteCode/Floating.h similarity index 100% rename from clang/lib/AST/Interp/Floating.h rename to clang/lib/AST/ByteCode/Floating.h diff --git a/clang/lib/AST/Interp/Frame.cpp b/clang/lib/AST/ByteCode/Frame.cpp similarity index 100% rename from clang/lib/AST/Interp/Frame.cpp rename to clang/lib/AST/ByteCode/Frame.cpp diff --git a/clang/lib/AST/Interp/Frame.h b/clang/lib/AST/ByteCode/Frame.h similarity index 100% rename from clang/lib/AST/Interp/Frame.h rename to clang/lib/AST/ByteCode/Frame.h diff --git a/clang/lib/AST/Interp/Function.cpp b/clang/lib/AST/ByteCode/Function.cpp similarity index 75% rename from clang/lib/AST/Interp/Function.cpp rename to clang/lib/AST/ByteCode/Function.cpp index 00f5a1fced531a9..e3fab3f6720b41e 100644 --- a/clang/lib/AST/Interp/Function.cpp +++ b/clang/lib/AST/ByteCode/Function.cpp @@ -16,16 +16,18 @@ using namespace clang; using namespace clang::interp; -Function::Function(Program &P, const FunctionDecl *F, unsigned ArgSize, +Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize, llvm::SmallVectorImpl &&ParamTypes, llvm::DenseMap &&Params, llvm::SmallVectorImpl &&ParamOffsets, bool HasThisPointer, bool HasRVO, bool UnevaluatedBuiltin) - : P(P), Loc(F->getBeginLoc()), F(F), ArgSize(ArgSize), - ParamTypes(std::move(ParamTypes)), Params(std::move(Params)), - ParamOffsets(std::move(ParamOffsets)), HasThisPointer(HasThisPointer), - HasRVO(HasRVO), Variadic(F->isVariadic()), - IsUnevaluatedBuiltin(UnevaluatedBuiltin) {} + : P(P), Source(Source), ArgSize(ArgSize), ParamTypes(std::move(ParamTypes)), + Params(std::move(Params)), ParamOffsets(std::move(ParamOffsets)), + HasThisPointer(HasThisPointer), HasRVO(HasRVO), + IsUnevaluatedBuiltin(UnevaluatedBuiltin) { + if (const auto *F = Source.dyn_cast()) + Variadic = F->isVariadic(); +} Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { auto It = Params.find(Offset); @@ -46,7 +48,8 @@ SourceInfo Function::getSource(CodePtr PC) const { } bool Function::isVirtual() const { - if (const auto *M = dyn_cast(F)) + if (const auto *M = dyn_cast_if_present( + Source.dyn_cast())) return M->isVirtual(); return false; } diff --git a/clang/lib/AST/Interp/Function.h b/clang/lib/AST/ByteCode/Function.h similarity index 85% rename from clang/lib/AST/Interp/Function.h rename to clang/lib/AST/ByteCode/Function.h index 92bcd96927912db..f254db20d4f5946 100644 --- a/clang/lib/AST/Interp/Function.h +++ b/clang/lib/AST/ByteCode/Function.h @@ -20,6 +20,7 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -55,6 +56,9 @@ class Scope final { LocalVectorTy Descriptors; }; +using FunctionDeclTy = + llvm::PointerUnion; + /// Bytecode function. /// /// Contains links to the bytecode of the function, as well as metadata @@ -89,20 +93,22 @@ class Function final { CodePtr getCodeEnd() const { return Code.data() + Code.size(); } /// Returns the original FunctionDecl. - const FunctionDecl *getDecl() const { return F; } + const FunctionDecl *getDecl() const { + return Source.dyn_cast(); + } + const BlockExpr *getExpr() const { + return Source.dyn_cast(); + } /// Returns the name of the function decl this code /// was generated for. const std::string getName() const { - if (!F) + if (!Source) return "<>"; - return F->getQualifiedNameAsString(); + return Source.get()->getQualifiedNameAsString(); } - /// Returns the location. - SourceLocation getLoc() const { return Loc; } - /// Returns a parameter descriptor. ParamDescriptor getParamDescriptor(unsigned Offset) const; @@ -138,13 +144,20 @@ class Function final { bool isVirtual() const; /// Checks if the function is a constructor. - bool isConstructor() const { return isa(F); } + bool isConstructor() const { + return isa_and_nonnull( + Source.dyn_cast()); + } /// Checks if the function is a destructor. - bool isDestructor() const { return isa(F); } + bool isDestructor() const { + return isa_and_nonnull( + Source.dyn_cast()); + } /// Returns the parent record decl, if any. const CXXRecordDecl *getParentDecl() const { - if (const auto *MD = dyn_cast(F)) + if (const auto *MD = dyn_cast_if_present( + Source.dyn_cast())) return MD->getParent(); return nullptr; } @@ -152,7 +165,8 @@ class Function final { /// Returns whether this function is a lambda static invoker, /// which we generate custom byte code for. bool isLambdaStaticInvoker() const { - if (const auto *MD = dyn_cast(F)) + if (const auto *MD = dyn_cast_if_present( + Source.dyn_cast())) return MD->isLambdaStaticInvoker(); return false; } @@ -160,7 +174,8 @@ class Function final { /// Returns whether this function is the call operator /// of a lambda record decl. bool isLambdaCallOperator() const { - if (const auto *MD = dyn_cast(F)) + if (const auto *MD = dyn_cast_if_present( + Source.dyn_cast())) return clang::isLambdaCallOperator(MD); return false; } @@ -178,9 +193,13 @@ class Function final { bool isVariadic() const { return Variadic; } - unsigned getBuiltinID() const { return F->getBuiltinID(); } + unsigned getBuiltinID() const { + return Source.get()->getBuiltinID(); + } - bool isBuiltin() const { return F->getBuiltinID() != 0; } + bool isBuiltin() const { + return Source.get()->getBuiltinID() != 0; + } bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; } @@ -197,7 +216,8 @@ class Function final { } bool isThisPointerExplicit() const { - if (const auto *MD = dyn_cast(F)) + if (const auto *MD = dyn_cast_if_present( + Source.dyn_cast())) return MD->isExplicitObjectMemberFunction(); return false; } @@ -208,7 +228,7 @@ class Function final { private: /// Construct a function representing an actual function. - Function(Program &P, const FunctionDecl *F, unsigned ArgSize, + Function(Program &P, FunctionDeclTy Source, unsigned ArgSize, llvm::SmallVectorImpl &&ParamTypes, llvm::DenseMap &&Params, llvm::SmallVectorImpl &&ParamOffsets, bool HasThisPointer, @@ -235,10 +255,8 @@ class Function final { /// Program reference. Program &P; - /// Location of the executed code. - SourceLocation Loc; /// Declaration this function was compiled from. - const FunctionDecl *F; + FunctionDeclTy Source; /// Local area size: storage + metadata. unsigned FrameSize = 0; /// Size of the argument stack. diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/ByteCode/FunctionPointer.h similarity index 90% rename from clang/lib/AST/Interp/FunctionPointer.h rename to clang/lib/AST/ByteCode/FunctionPointer.h index d92cd32933fcdce..c9bdfbee55441a3 100644 --- a/clang/lib/AST/Interp/FunctionPointer.h +++ b/clang/lib/AST/ByteCode/FunctionPointer.h @@ -33,7 +33,7 @@ class FunctionPointer final { bool isZero() const { return !Func; } bool isValid() const { return Valid; } bool isWeak() const { - if (!Func || !Valid) + if (!Func || !Valid || !Func->getDecl()) return false; return Func->getDecl()->isWeak(); @@ -49,7 +49,10 @@ class FunctionPointer final { CharUnits::fromQuantity(getIntegerRepresentation()), {}, /*OnePastTheEnd=*/false, /*IsNull=*/false); - return APValue(Func->getDecl(), CharUnits::Zero(), {}, + if (Func->getDecl()) + return APValue(Func->getDecl(), CharUnits::Zero(), {}, + /*OnePastTheEnd=*/false, /*IsNull=*/false); + return APValue(Func->getExpr(), CharUnits::Zero(), {}, /*OnePastTheEnd=*/false, /*IsNull=*/false); } diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/ByteCode/Integral.h similarity index 93% rename from clang/lib/AST/Interp/Integral.h rename to clang/lib/AST/ByteCode/Integral.h index aafdd02676c966f..e06ec1669259da4 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/ByteCode/Integral.h @@ -13,8 +13,8 @@ #ifndef LLVM_CLANG_AST_INTERP_INTEGRAL_H #define LLVM_CLANG_AST_INTERP_INTEGRAL_H -#include "clang/AST/ComparisonCategories.h" #include "clang/AST/APValue.h" +#include "clang/AST/ComparisonCategories.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -33,14 +33,30 @@ template class IntegralAP; // Helper structure to select the representation. template struct Repr; -template <> struct Repr<8, false> { using Type = uint8_t; }; -template <> struct Repr<16, false> { using Type = uint16_t; }; -template <> struct Repr<32, false> { using Type = uint32_t; }; -template <> struct Repr<64, false> { using Type = uint64_t; }; -template <> struct Repr<8, true> { using Type = int8_t; }; -template <> struct Repr<16, true> { using Type = int16_t; }; -template <> struct Repr<32, true> { using Type = int32_t; }; -template <> struct Repr<64, true> { using Type = int64_t; }; +template <> struct Repr<8, false> { + using Type = uint8_t; +}; +template <> struct Repr<16, false> { + using Type = uint16_t; +}; +template <> struct Repr<32, false> { + using Type = uint32_t; +}; +template <> struct Repr<64, false> { + using Type = uint64_t; +}; +template <> struct Repr<8, true> { + using Type = int8_t; +}; +template <> struct Repr<16, true> { + using Type = int16_t; +}; +template <> struct Repr<32, true> { + using Type = int32_t; +}; +template <> struct Repr<64, true> { + using Type = int64_t; +}; /// Wrapper around numeric types. /// @@ -159,12 +175,8 @@ template class Integral final { void print(llvm::raw_ostream &OS) const { OS << V; } - static Integral min(unsigned NumBits) { - return Integral(Min); - } - static Integral max(unsigned NumBits) { - return Integral(Max); - } + static Integral min(unsigned NumBits) { return Integral(Min); } + static Integral max(unsigned NumBits) { return Integral(Max); } template static Integral from(ValT Value) { if constexpr (std::is_integral::value) diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/ByteCode/IntegralAP.h similarity index 100% rename from clang/lib/AST/Interp/IntegralAP.h rename to clang/lib/AST/ByteCode/IntegralAP.h diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp similarity index 100% rename from clang/lib/AST/Interp/Interp.cpp rename to clang/lib/AST/ByteCode/Interp.cpp diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/ByteCode/Interp.h similarity index 98% rename from clang/lib/AST/Interp/Interp.h rename to clang/lib/AST/ByteCode/Interp.h index 3eab0cfd871385a..bad46e983048455 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -656,15 +656,9 @@ inline bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { // Inv //===----------------------------------------------------------------------===// -template ::T> -bool Inv(InterpState &S, CodePtr OpPC) { - using BoolT = PrimConv::T; - const T &Val = S.Stk.pop(); - const unsigned Bits = Val.bitWidth(); - Boolean R; - Boolean::inv(BoolT::from(Val, Bits), &R); - - S.Stk.push(R); +inline bool Inv(InterpState &S, CodePtr OpPC) { + const auto &Val = S.Stk.pop(); + S.Stk.push(!Val); return true; } @@ -1226,7 +1220,7 @@ template ::T> bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Obj = S.Stk.peek(); if (!CheckNull(S, OpPC, Obj, CSK_Field)) - return false; + return false; if (!CheckRange(S, OpPC, Obj, CSK_Field)) return false; const Pointer &Field = Obj.atField(I); @@ -1542,7 +1536,7 @@ inline bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off) { } inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) { - if (S.checkingPotentialConstantExpression()) + if (S.checkingPotentialConstantExpression()) return false; const Pointer &This = S.Current->getThis(); if (!CheckThis(S, OpPC, This)) @@ -1853,6 +1847,17 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, if (!CheckArray(S, OpPC, Ptr)) return false; + // This is much simpler for integral pointers, so handle them first. + if (Ptr.isIntegralPointer()) { + uint64_t V = Ptr.getIntegerRepresentation(); + uint64_t O = static_cast(Offset) * Ptr.elemSize(); + if constexpr (Op == ArithOp::Add) + S.Stk.push(V + O, Ptr.asIntPointer().Desc); + else + S.Stk.push(V - O, Ptr.asIntPointer().Desc); + return true; + } + uint64_t MaxIndex = static_cast(Ptr.getNumElems()); uint64_t Index; if (Ptr.isOnePastEnd()) @@ -2053,7 +2058,7 @@ template bool Cast(InterpState &S, CodePtr OpPC) { /// 1) Pops a Floating from the stack. /// 2) Pushes a new floating on the stack that uses the given semantics. inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, - llvm::RoundingMode RM) { + llvm::RoundingMode RM) { Floating F = S.Stk.pop(); Floating Result = F.toSemantics(Sem, RM); S.Stk.push(Result); @@ -2313,9 +2318,9 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) { if (!S.noteUndefinedBehavior()) return false; RHS = -RHS; - return DoShift < LT, RT, - Dir == ShiftDir::Left ? ShiftDir::Right - : ShiftDir::Left > (S, OpPC, LHS, RHS); + return DoShift( + S, OpPC, LHS, RHS); } if constexpr (Dir == ShiftDir::Left) { @@ -2354,6 +2359,17 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) { LT::AsUnsigned::from(RHS, Bits), Bits, &R); } + // We did the shift above as unsigned. Restore the sign bit if we need to. + if constexpr (Dir == ShiftDir::Right) { + if (LHS.isSigned() && LHS.isNegative()) { + typename LT::AsUnsigned SignBit; + LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(1, Bits), + LT::AsUnsigned::from(Bits - 1, Bits), Bits, + &SignBit); + LT::AsUnsigned::bitOr(R, SignBit, Bits, &R); + } + } + S.Stk.push(LT::from(R)); return true; } @@ -2467,7 +2483,8 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { } template ::T> -inline bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex, uint32_t DestIndex, uint32_t Size) { +inline bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex, + uint32_t DestIndex, uint32_t Size) { const auto &SrcPtr = S.Stk.pop(); const auto &DestPtr = S.Stk.peek(); @@ -2702,13 +2719,13 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const Function *F = FuncPtr.getFunction(); if (!F) { - const Expr *E = S.Current->getExpr(OpPC); + const auto *E = cast(S.Current->getExpr(OpPC)); S.FFDiag(E, diag::note_constexpr_null_callee) - << const_cast(E) << E->getSourceRange(); + << const_cast(E->getCallee()) << E->getSourceRange(); return false; } - if (!FuncPtr.isValid()) + if (!FuncPtr.isValid() || !F->getDecl()) return Invalid(S, OpPC); assert(F); diff --git a/clang/lib/AST/Interp/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp similarity index 100% rename from clang/lib/AST/Interp/InterpBlock.cpp rename to clang/lib/AST/ByteCode/InterpBlock.cpp diff --git a/clang/lib/AST/Interp/InterpBlock.h b/clang/lib/AST/ByteCode/InterpBlock.h similarity index 100% rename from clang/lib/AST/Interp/InterpBlock.h rename to clang/lib/AST/ByteCode/InterpBlock.h index 20cf8cb9d3810e9..a5cd58e3a655a0c 100644 --- a/clang/lib/AST/Interp/InterpBlock.h +++ b/clang/lib/AST/ByteCode/InterpBlock.h @@ -14,10 +14,10 @@ #define LLVM_CLANG_AST_INTERP_BLOCK_H #include "Descriptor.h" +#include "clang/AST/ComparisonCategories.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" -#include "clang/AST/ComparisonCategories.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp similarity index 96% rename from clang/lib/AST/Interp/InterpBuiltin.cpp rename to clang/lib/AST/ByteCode/InterpBuiltin.cpp index c3370e2e5286e07..26abf5820510673 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -433,6 +433,51 @@ static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, const Function *F, + const CallExpr *Call) { + const Floating &Arg = S.Stk.peek(); + + pushInteger(S, Arg.isNegative(), Call->getType()); + return true; +} + +static bool interp_floating_comparison(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *F, + const CallExpr *Call) { + const Floating &RHS = S.Stk.peek(); + const Floating &LHS = S.Stk.peek(align(2u * primSize(PT_Float))); + unsigned ID = F->getBuiltinID(); + + pushInteger( + S, + [&] { + switch (ID) { + case Builtin::BI__builtin_isgreater: + return LHS > RHS; + case Builtin::BI__builtin_isgreaterequal: + return LHS >= RHS; + case Builtin::BI__builtin_isless: + return LHS < RHS; + case Builtin::BI__builtin_islessequal: + return LHS <= RHS; + case Builtin::BI__builtin_islessgreater: { + ComparisonCategoryResult cmp = LHS.compare(RHS); + return cmp == ComparisonCategoryResult::Less || + cmp == ComparisonCategoryResult::Greater; + } + case Builtin::BI__builtin_isunordered: + return LHS.compare(RHS) == ComparisonCategoryResult::Unordered; + default: + llvm_unreachable("Unexpected builtin ID: Should be a floating point " + "comparison function"); + } + }(), + Call->getType()); + return true; +} + /// First parameter to __builtin_isfpclass is the floating value, the /// second one is an integral value. static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, @@ -1313,6 +1358,21 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, if (!interp__builtin_iszero(S, OpPC, Frame, F, Call)) return false; break; + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: + if (!interp__builtin_signbit(S, OpPC, Frame, F, Call)) + return false; + break; + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: + if (!interp_floating_comparison(S, OpPC, Frame, F, Call)) + return false; + break; case Builtin::BI__builtin_isfpclass: if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call)) return false; diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp similarity index 99% rename from clang/lib/AST/Interp/InterpFrame.cpp rename to clang/lib/AST/ByteCode/InterpFrame.cpp index 4530f28d694e844..8b55b61cbbfa7e5 100644 --- a/clang/lib/AST/Interp/InterpFrame.cpp +++ b/clang/lib/AST/ByteCode/InterpFrame.cpp @@ -137,7 +137,7 @@ void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx, if (!Ty->isReferenceType()) OS << "&"; llvm::SmallVector Levels; - for (Pointer F = P; !F.isRoot(); ) { + for (Pointer F = P; !F.isRoot();) { Levels.push_back(F); F = F.isArrayElement() ? F.getArray().expand() : F.getBase(); } diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/ByteCode/InterpFrame.h similarity index 99% rename from clang/lib/AST/Interp/InterpFrame.h rename to clang/lib/AST/ByteCode/InterpFrame.h index 91b9b41b5d33431..1e0d2b1d4424b14 100644 --- a/clang/lib/AST/Interp/InterpFrame.h +++ b/clang/lib/AST/ByteCode/InterpFrame.h @@ -91,7 +91,7 @@ class InterpFrame final : public Frame { /// Mutates a local copy of a parameter. template void setParam(unsigned Offset, const T &Value) { - getParamPointer(Offset).deref() = Value; + getParamPointer(Offset).deref() = Value; } /// Returns a pointer to an argument - lazily creates a block. diff --git a/clang/lib/AST/Interp/InterpShared.cpp b/clang/lib/AST/ByteCode/InterpShared.cpp similarity index 100% rename from clang/lib/AST/Interp/InterpShared.cpp rename to clang/lib/AST/ByteCode/InterpShared.cpp diff --git a/clang/lib/AST/Interp/InterpShared.h b/clang/lib/AST/ByteCode/InterpShared.h similarity index 100% rename from clang/lib/AST/Interp/InterpShared.h rename to clang/lib/AST/ByteCode/InterpShared.h diff --git a/clang/lib/AST/Interp/InterpStack.cpp b/clang/lib/AST/ByteCode/InterpStack.cpp similarity index 98% rename from clang/lib/AST/Interp/InterpStack.cpp rename to clang/lib/AST/ByteCode/InterpStack.cpp index c7024740d322ef2..b8cdaeee72166cf 100644 --- a/clang/lib/AST/Interp/InterpStack.cpp +++ b/clang/lib/AST/ByteCode/InterpStack.cpp @@ -18,9 +18,7 @@ using namespace clang; using namespace clang::interp; -InterpStack::~InterpStack() { - clear(); -} +InterpStack::~InterpStack() { clear(); } void InterpStack::clear() { if (Chunk && Chunk->Next) diff --git a/clang/lib/AST/Interp/InterpStack.h b/clang/lib/AST/ByteCode/InterpStack.h similarity index 97% rename from clang/lib/AST/Interp/InterpStack.h rename to clang/lib/AST/ByteCode/InterpStack.h index 4966e2870de6bd9..153d17f0d70e1bd 100644 --- a/clang/lib/AST/Interp/InterpStack.h +++ b/clang/lib/AST/ByteCode/InterpStack.h @@ -32,7 +32,7 @@ class InterpStack final { ~InterpStack(); /// Constructs a value in place on the top of the stack. - template void push(Tys &&... Args) { + template void push(Tys &&...Args) { new (grow(aligned_size())) T(std::forward(Args)...); #ifndef NDEBUG ItemTypes.push_back(toPrimType()); @@ -153,8 +153,7 @@ class InterpStack final { template static constexpr PrimType toPrimType() { if constexpr (std::is_same_v) return PT_Ptr; - else if constexpr (std::is_same_v || - std::is_same_v) + else if constexpr (std::is_same_v || std::is_same_v) return PT_Bool; else if constexpr (std::is_same_v || std::is_same_v>) diff --git a/clang/lib/AST/Interp/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp similarity index 100% rename from clang/lib/AST/Interp/InterpState.cpp rename to clang/lib/AST/ByteCode/InterpState.cpp diff --git a/clang/lib/AST/Interp/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h similarity index 100% rename from clang/lib/AST/Interp/InterpState.h rename to clang/lib/AST/ByteCode/InterpState.h diff --git a/clang/lib/AST/Interp/MemberPointer.cpp b/clang/lib/AST/ByteCode/MemberPointer.cpp similarity index 64% rename from clang/lib/AST/Interp/MemberPointer.cpp rename to clang/lib/AST/ByteCode/MemberPointer.cpp index 0c1b6edc5f7e105..0fe94db97a3c403 100644 --- a/clang/lib/AST/Interp/MemberPointer.cpp +++ b/clang/lib/AST/ByteCode/MemberPointer.cpp @@ -18,8 +18,7 @@ namespace interp { std::optional MemberPointer::toPointer(const Context &Ctx) const { if (!Dcl || isa(Dcl)) return Base; - const FieldDecl *FD = cast(Dcl); - assert(FD); + assert((isa(Dcl))); if (!Base.isBlockPointer()) return std::nullopt; @@ -31,24 +30,36 @@ std::optional MemberPointer::toPointer(const Context &Ctx) const { if (!BaseRecord) return std::nullopt; - assert(BaseRecord); - if (FD->getParent() == BaseRecord->getDecl()) - return CastedBase.atField(BaseRecord->getField(FD)->Offset); - - const RecordDecl *FieldParent = FD->getParent(); - const Record *FieldRecord = Ctx.getRecord(FieldParent); - unsigned Offset = 0; - Offset += FieldRecord->getField(FD)->Offset; Offset += CastedBase.block()->getDescriptor()->getMetadataSize(); - if (Offset > CastedBase.block()->getSize()) - return std::nullopt; + if (const auto *FD = dyn_cast(Dcl)) { + if (FD->getParent() == BaseRecord->getDecl()) + return CastedBase.atField(BaseRecord->getField(FD)->Offset); - if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl(); - BaseDecl != FieldParent) - Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl); + const RecordDecl *FieldParent = FD->getParent(); + const Record *FieldRecord = Ctx.getRecord(FieldParent); + Offset += FieldRecord->getField(FD)->Offset; + if (Offset > CastedBase.block()->getSize()) + return std::nullopt; + + if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl(); + BaseDecl != FieldParent) + Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl); + + } else { + const auto *IFD = cast(Dcl); + + for (const NamedDecl *ND : IFD->chain()) { + const FieldDecl *F = cast(ND); + const RecordDecl *FieldParent = F->getParent(); + const Record *FieldRecord = Ctx.getRecord(FieldParent); + Offset += FieldRecord->getField(F)->Offset; + } + } + + assert(BaseRecord); if (Offset > CastedBase.block()->getSize()) return std::nullopt; diff --git a/clang/lib/AST/Interp/MemberPointer.h b/clang/lib/AST/ByteCode/MemberPointer.h similarity index 100% rename from clang/lib/AST/Interp/MemberPointer.h rename to clang/lib/AST/ByteCode/MemberPointer.h diff --git a/clang/lib/AST/Interp/Opcode.h b/clang/lib/AST/ByteCode/Opcode.h similarity index 100% rename from clang/lib/AST/Interp/Opcode.h rename to clang/lib/AST/ByteCode/Opcode.h diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td similarity index 99% rename from clang/lib/AST/Interp/Opcodes.td rename to clang/lib/AST/ByteCode/Opcodes.td index 3478eb174e518ed..61319e1633d9ad4 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -103,10 +103,6 @@ def PtrTypeClass : TypeClass { let Types = [Ptr, FnPtr, MemberPtr]; } -def BoolTypeClass : TypeClass { - let Types = [Bool]; -} - def NonPtrTypeClass : TypeClass { let Types = !listconcat(IntegerTypeClass.Types, [Bool], [Float]); } @@ -574,11 +570,8 @@ def Shr : Opcode { // Unary operators. //===----------------------------------------------------------------------===// -// [Real] -> [Real] -def Inv: Opcode { - let Types = [BoolTypeClass]; - let HasGroup = 1; -} +// [Bool] -> [Bool] +def Inv: Opcode; // Increment and decrement. def Inc: AluOpcode; diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp similarity index 97% rename from clang/lib/AST/Interp/Pointer.cpp rename to clang/lib/AST/ByteCode/Pointer.cpp index 466e61666c76e92..5b9e83764cfa503 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -265,10 +265,10 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { } void Pointer::print(llvm::raw_ostream &OS) const { - OS << PointeeStorage.BS.Pointee << " ("; - if (isBlockPointer()) { + switch (StorageKind) { + case Storage::Block: { const Block *B = PointeeStorage.BS.Pointee; - OS << "Block) {"; + OS << "(Block) " << B << " {"; if (isRoot()) OS << "rootptr(" << PointeeStorage.BS.Base << "), "; @@ -284,11 +284,18 @@ void Pointer::print(llvm::raw_ostream &OS) const { OS << B->getSize(); else OS << "nullptr"; - } else { - OS << "Int) {"; - OS << PointeeStorage.Int.Value << ", " << PointeeStorage.Int.Desc; + OS << "}"; + } break; + case Storage::Int: + OS << "(Int) {"; + OS << PointeeStorage.Int.Value << " + " << Offset << ", " + << PointeeStorage.Int.Desc; + OS << "}"; + break; + case Storage::Fn: + OS << "(Fn) { " << asFunctionPointer().getFunction() << " + " << Offset + << " }"; } - OS << "}"; } std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const { @@ -647,5 +654,5 @@ IntPointer IntPointer::atOffset(const ASTContext &ASTCtx, uint64_t FieldOffset = ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex)) .getQuantity(); - return IntPointer{this->Desc, FieldOffset}; + return IntPointer{this->Desc, this->Value + FieldOffset}; } diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h similarity index 99% rename from clang/lib/AST/Interp/Pointer.h rename to clang/lib/AST/ByteCode/Pointer.h index 01ccb88ec03b292..ba30449977376bb 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -173,7 +173,7 @@ class Pointer { /// Subtract the given offset from the current Base and Offset /// of the pointer. - [[nodiscard]] Pointer atFieldSub(unsigned Off) const { + [[nodiscard]] Pointer atFieldSub(unsigned Off) const { assert(Offset >= Off); unsigned O = Offset - Off; return Pointer(asBlockPointer().Pointee, O, O); @@ -571,7 +571,7 @@ class Pointer { /// Returns the index into an array. int64_t getIndex() const { if (!isBlockPointer()) - return 0; + return getIntegerRepresentation(); if (isZero()) return 0; diff --git a/clang/lib/AST/Interp/PrimType.cpp b/clang/lib/AST/ByteCode/PrimType.cpp similarity index 100% rename from clang/lib/AST/Interp/PrimType.cpp rename to clang/lib/AST/ByteCode/PrimType.cpp diff --git a/clang/lib/AST/Interp/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h similarity index 83% rename from clang/lib/AST/Interp/PrimType.h rename to clang/lib/AST/ByteCode/PrimType.h index 20fb5e81774d6ff..bb2f59d86e98d78 100644 --- a/clang/lib/AST/Interp/PrimType.h +++ b/clang/lib/AST/ByteCode/PrimType.h @@ -73,23 +73,45 @@ constexpr bool isIntegralType(PrimType T) { return T <= PT_Bool; } /// Mapping from primitive types to their representation. template struct PrimConv; -template <> struct PrimConv { using T = Integral<8, true>; }; -template <> struct PrimConv { using T = Integral<8, false>; }; -template <> struct PrimConv { using T = Integral<16, true>; }; -template <> struct PrimConv { using T = Integral<16, false>; }; -template <> struct PrimConv { using T = Integral<32, true>; }; -template <> struct PrimConv { using T = Integral<32, false>; }; -template <> struct PrimConv { using T = Integral<64, true>; }; -template <> struct PrimConv { using T = Integral<64, false>; }; +template <> struct PrimConv { + using T = Integral<8, true>; +}; +template <> struct PrimConv { + using T = Integral<8, false>; +}; +template <> struct PrimConv { + using T = Integral<16, true>; +}; +template <> struct PrimConv { + using T = Integral<16, false>; +}; +template <> struct PrimConv { + using T = Integral<32, true>; +}; +template <> struct PrimConv { + using T = Integral<32, false>; +}; +template <> struct PrimConv { + using T = Integral<64, true>; +}; +template <> struct PrimConv { + using T = Integral<64, false>; +}; template <> struct PrimConv { using T = IntegralAP; }; template <> struct PrimConv { using T = IntegralAP; }; -template <> struct PrimConv { using T = Floating; }; -template <> struct PrimConv { using T = Boolean; }; -template <> struct PrimConv { using T = Pointer; }; +template <> struct PrimConv { + using T = Floating; +}; +template <> struct PrimConv { + using T = Boolean; +}; +template <> struct PrimConv { + using T = Pointer; +}; template <> struct PrimConv { using T = FunctionPointer; }; @@ -117,8 +139,12 @@ static inline bool aligned(const void *P) { /// Helper macro to simplify type switches. /// The macro implicitly exposes a type T in the scope of the inner block. -#define TYPE_SWITCH_CASE(Name, B) \ - case Name: { using T = PrimConv::T; B; break; } +#define TYPE_SWITCH_CASE(Name, B) \ + case Name: { \ + using T = PrimConv::T; \ + B; \ + break; \ + } #define TYPE_SWITCH(Expr, B) \ do { \ switch (Expr) { \ @@ -181,7 +207,10 @@ static inline bool aligned(const void *P) { do { \ switch (Expr) { \ TYPE_SWITCH_CASE(PT_Ptr, B) \ - default: { D; break; } \ + default: { \ + D; \ + break; \ + } \ } \ } while (0) #endif diff --git a/clang/lib/AST/Interp/Primitives.h b/clang/lib/AST/ByteCode/Primitives.h similarity index 100% rename from clang/lib/AST/Interp/Primitives.h rename to clang/lib/AST/ByteCode/Primitives.h diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp similarity index 95% rename from clang/lib/AST/Interp/Program.cpp rename to clang/lib/AST/ByteCode/Program.cpp index 5dd59d969853cce..a4f0df8bf6462e0 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -76,26 +76,26 @@ unsigned Program::createGlobalString(const StringLiteral *S) { Pointer Field = Ptr.atIndex(I).narrow(); const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I); switch (CharType) { - case PT_Sint8: { - using T = PrimConv::T; - Field.deref() = T::from(CodePoint, BitWidth); - Field.initialize(); - break; - } - case PT_Uint16: { - using T = PrimConv::T; - Field.deref() = T::from(CodePoint, BitWidth); - Field.initialize(); - break; - } - case PT_Uint32: { - using T = PrimConv::T; - Field.deref() = T::from(CodePoint, BitWidth); - Field.initialize(); - break; - } - default: - llvm_unreachable("unsupported character type"); + case PT_Sint8: { + using T = PrimConv::T; + Field.deref() = T::from(CodePoint, BitWidth); + Field.initialize(); + break; + } + case PT_Uint16: { + using T = PrimConv::T; + Field.deref() = T::from(CodePoint, BitWidth); + Field.initialize(); + break; + } + case PT_Uint32: { + using T = PrimConv::T; + Field.deref() = T::from(CodePoint, BitWidth); + Field.initialize(); + break; + } + default: + llvm_unreachable("unsupported character type"); } } return I; @@ -329,6 +329,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { // Reserve space for fields. Record::FieldList Fields; for (const FieldDecl *FD : RD->fields()) { + FD = FD->getFirstDecl(); // Note that we DO create fields and descriptors // for unnamed bitfields here, even though we later ignore // them everywhere. That's so the FieldDecl's getFieldIndex() matches. @@ -393,8 +394,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary); if (!ElemDesc) return nullptr; - unsigned ElemSize = - ElemDesc->getAllocSize() + sizeof(InlineDescriptor); + unsigned ElemSize = ElemDesc->getAllocSize() + sizeof(InlineDescriptor); if (std::numeric_limits::max() / ElemSize <= NumElems) return {}; return allocateDescriptor(D, ElemDesc, MDSize, NumElems, IsConst, diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/ByteCode/Program.h similarity index 96% rename from clang/lib/AST/Interp/Program.h rename to clang/lib/AST/ByteCode/Program.h index 1cabc5212180f28..7f69d9790fc79ac 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/ByteCode/Program.h @@ -13,8 +13,6 @@ #ifndef LLVM_CLANG_AST_INTERP_PROGRAM_H #define LLVM_CLANG_AST_INTERP_PROGRAM_H -#include -#include #include "Function.h" #include "Pointer.h" #include "PrimType.h" @@ -24,6 +22,8 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include +#include namespace clang { class RecordDecl; @@ -94,15 +94,14 @@ class Program final { /// Creates a new function from a code range. template - Function *createFunction(const FunctionDecl *Def, Ts &&... Args) { + Function *createFunction(const FunctionDecl *Def, Ts &&...Args) { Def = Def->getCanonicalDecl(); auto *Func = new Function(*this, Def, std::forward(Args)...); Funcs.insert({Def, std::unique_ptr(Func)}); return Func; } /// Creates an anonymous function. - template - Function *createFunction(Ts &&... Args) { + template Function *createFunction(Ts &&...Args) { auto *Func = new Function(*this, std::forward(Args)...); AnonFuncs.emplace_back(Func); return Func; @@ -213,8 +212,7 @@ class Program final { llvm::DenseMap DummyVariables; /// Creates a new descriptor. - template - Descriptor *allocateDescriptor(Ts &&... Args) { + template Descriptor *allocateDescriptor(Ts &&...Args) { return new (Allocator) Descriptor(std::forward(Args)...); } @@ -232,9 +230,7 @@ class Program final { } /// Ends a global declaration. - void endDeclaration() { - CurrentDeclaration = NoDeclaration; - } + void endDeclaration() { CurrentDeclaration = NoDeclaration; } public: /// Dumps the disassembled bytecode to \c llvm::errs(). diff --git a/clang/lib/AST/Interp/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp similarity index 94% rename from clang/lib/AST/Interp/Record.cpp rename to clang/lib/AST/ByteCode/Record.cpp index ac01524e1caf0d7..ec1b55da347af66 100644 --- a/clang/lib/AST/Interp/Record.cpp +++ b/clang/lib/AST/ByteCode/Record.cpp @@ -18,7 +18,7 @@ Record::Record(const RecordDecl *Decl, BaseList &&SrcBases, : Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)), BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()) { for (Base &V : SrcVirtualBases) - VirtualBases.push_back({ V.Decl, V.Offset + BaseSize, V.Desc, V.R }); + VirtualBases.push_back({V.Decl, V.Offset + BaseSize, V.Desc, V.R}); for (Base &B : Bases) BaseMap[B.Decl] = &B; @@ -37,7 +37,7 @@ const std::string Record::getName() const { } const Record::Field *Record::getField(const FieldDecl *FD) const { - auto It = FieldMap.find(FD); + auto It = FieldMap.find(FD->getFirstDecl()); assert(It != FieldMap.end() && "Missing field"); return It->second; } diff --git a/clang/lib/AST/Interp/Record.h b/clang/lib/AST/ByteCode/Record.h similarity index 100% rename from clang/lib/AST/Interp/Record.h rename to clang/lib/AST/ByteCode/Record.h diff --git a/clang/lib/AST/Interp/Source.cpp b/clang/lib/AST/ByteCode/Source.cpp similarity index 100% rename from clang/lib/AST/Interp/Source.cpp rename to clang/lib/AST/ByteCode/Source.cpp diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/ByteCode/Source.h similarity index 100% rename from clang/lib/AST/Interp/Source.h rename to clang/lib/AST/ByteCode/Source.h diff --git a/clang/lib/AST/Interp/State.cpp b/clang/lib/AST/ByteCode/State.cpp similarity index 100% rename from clang/lib/AST/Interp/State.cpp rename to clang/lib/AST/ByteCode/State.cpp diff --git a/clang/lib/AST/Interp/State.h b/clang/lib/AST/ByteCode/State.h similarity index 100% rename from clang/lib/AST/Interp/State.h rename to clang/lib/AST/ByteCode/State.h diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 70aecb781c2ff2f..041252b6830e0a7 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -11,7 +11,7 @@ set(LLVM_LINK_COMPONENTS # another library which depends on clangAST. clang_tablegen(Opcodes.inc -gen-clang-opcodes - SOURCE Interp/Opcodes.td + SOURCE ByteCode/Opcodes.td TARGET Opcodes) clang_tablegen(AttrDocTable.inc -gen-clang-attr-doc-table @@ -64,31 +64,31 @@ add_clang_library(clangAST ExternalASTSource.cpp FormatString.cpp InheritViz.cpp - Interp/ByteCodeEmitter.cpp - Interp/Compiler.cpp - Interp/Context.cpp - Interp/Descriptor.cpp - Interp/Disasm.cpp - Interp/EvalEmitter.cpp - Interp/Frame.cpp - Interp/Function.cpp - Interp/InterpBuiltin.cpp - Interp/Floating.cpp - Interp/EvaluationResult.cpp - Interp/DynamicAllocator.cpp - Interp/Interp.cpp - Interp/InterpBlock.cpp - Interp/InterpFrame.cpp - Interp/InterpStack.cpp - Interp/InterpState.cpp - Interp/Pointer.cpp - Interp/PrimType.cpp - Interp/Program.cpp - Interp/Record.cpp - Interp/Source.cpp - Interp/State.cpp - Interp/MemberPointer.cpp - Interp/InterpShared.cpp + ByteCode/ByteCodeEmitter.cpp + ByteCode/Compiler.cpp + ByteCode/Context.cpp + ByteCode/Descriptor.cpp + ByteCode/Disasm.cpp + ByteCode/EvalEmitter.cpp + ByteCode/Frame.cpp + ByteCode/Function.cpp + ByteCode/InterpBuiltin.cpp + ByteCode/Floating.cpp + ByteCode/EvaluationResult.cpp + ByteCode/DynamicAllocator.cpp + ByteCode/Interp.cpp + ByteCode/InterpBlock.cpp + ByteCode/InterpFrame.cpp + ByteCode/InterpStack.cpp + ByteCode/InterpState.cpp + ByteCode/Pointer.cpp + ByteCode/PrimType.cpp + ByteCode/Program.cpp + ByteCode/Record.cpp + ByteCode/Source.cpp + ByteCode/State.cpp + ByteCode/MemberPointer.cpp + ByteCode/InterpShared.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp JSONNodeDumper.cpp diff --git a/clang/lib/AST/DeclFriend.cpp b/clang/lib/AST/DeclFriend.cpp index 04b9b93699f36ce..8b285bfce8d5221 100644 --- a/clang/lib/AST/DeclFriend.cpp +++ b/clang/lib/AST/DeclFriend.cpp @@ -31,11 +31,11 @@ FriendDecl *FriendDecl::getNextFriendSlowCase() { NextFriend.get(getASTContext().getExternalSource())); } -FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - FriendUnion Friend, - SourceLocation FriendL, - ArrayRef FriendTypeTPLists) { +FriendDecl * +FriendDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, + FriendUnion Friend, SourceLocation FriendL, + SourceLocation EllipsisLoc, + ArrayRef FriendTypeTPLists) { #ifndef NDEBUG if (Friend.is()) { const auto *D = Friend.get(); @@ -56,8 +56,8 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, std::size_t Extra = FriendDecl::additionalSizeToAlloc( FriendTypeTPLists.size()); - auto *FD = new (C, DC, Extra) FriendDecl(DC, L, Friend, FriendL, - FriendTypeTPLists); + auto *FD = new (C, DC, Extra) + FriendDecl(DC, L, Friend, FriendL, EllipsisLoc, FriendTypeTPLists); cast(DC)->pushFriendDecl(FD); return FD; } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 26773a69ab9acff..07be813abd8adca 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -868,7 +868,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) { for (unsigned i = 0; i < NumTPLists; ++i) printTemplateParameters(D->getFriendTypeTemplateParameterList(i)); Out << "friend "; - Out << " " << TSI->getType().getAsString(Policy); + Out << TSI->getType().getAsString(Policy); } else if (FunctionDecl *FD = dyn_cast(D->getFriendDecl())) { @@ -885,6 +885,9 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) { Out << "friend "; VisitRedeclarableTemplateDecl(CTD); } + + if (D->isPackExpansion()) + Out << "..."; } void DeclPrinter::VisitFieldDecl(FieldDecl *D) { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 57475c66a94e356..9d5b8167d0ee628 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -4759,53 +4759,6 @@ ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx, return new (Mem) ParenListExpr(EmptyShell(), NumExprs); } -/// Certain overflow-dependent code patterns can have their integer overflow -/// sanitization disabled. Check for the common pattern `if (a + b < a)` and -/// return the resulting BinaryOperator responsible for the addition so we can -/// elide overflow checks during codegen. -static std::optional -getOverflowPatternBinOp(const BinaryOperator *E) { - Expr *Addition, *ComparedTo; - if (E->getOpcode() == BO_LT) { - Addition = E->getLHS(); - ComparedTo = E->getRHS(); - } else if (E->getOpcode() == BO_GT) { - Addition = E->getRHS(); - ComparedTo = E->getLHS(); - } else { - return {}; - } - - const Expr *AddLHS = nullptr, *AddRHS = nullptr; - BinaryOperator *BO = dyn_cast(Addition); - - if (BO && BO->getOpcode() == clang::BO_Add) { - // now store addends for lookup on other side of '>' - AddLHS = BO->getLHS(); - AddRHS = BO->getRHS(); - } - - if (!AddLHS || !AddRHS) - return {}; - - const Decl *LHSDecl, *RHSDecl, *OtherDecl; - - LHSDecl = AddLHS->IgnoreParenImpCasts()->getReferencedDeclOfCallee(); - RHSDecl = AddRHS->IgnoreParenImpCasts()->getReferencedDeclOfCallee(); - OtherDecl = ComparedTo->IgnoreParenImpCasts()->getReferencedDeclOfCallee(); - - if (!OtherDecl) - return {}; - - if (!LHSDecl && !RHSDecl) - return {}; - - if ((LHSDecl && LHSDecl == OtherDecl && LHSDecl != RHSDecl) || - (RHSDecl && RHSDecl == OtherDecl && RHSDecl != LHSDecl)) - return BO; - return {}; -} - BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, @@ -4815,15 +4768,8 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, assert(!isCompoundAssignmentOp() && "Use CompoundAssignOperator for compound assignments"); BinaryOperatorBits.OpLoc = opLoc; - BinaryOperatorBits.ExcludedOverflowPattern = 0; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - if (Ctx.getLangOpts().isOverflowPatternExcluded( - LangOptions::OverflowPatternExclusionKind::AddOverflowTest)) { - std::optional Result = getOverflowPatternBinOp(this); - if (Result.has_value()) - Result.value()->BinaryOperatorBits.ExcludedOverflowPattern = 1; - } BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); if (hasStoredFPFeatures()) setStoredFPFeatures(FPFeatures); diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h index 2a7088e4e371a1f..efe8ee986d29b3d 100644 --- a/clang/lib/AST/ExprConstShared.h +++ b/clang/lib/AST/ExprConstShared.h @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // // Shared functionality between the new constant expression -// interpreter (AST/Interp/) and the current one (ExprConstant.cpp). +// interpreter (AST/ByteCode/) and the current one (ExprConstant.cpp). // //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 09edbb6641650a0..5540f58b526705a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -32,10 +32,10 @@ // //===----------------------------------------------------------------------===// +#include "ByteCode/Context.h" +#include "ByteCode/Frame.h" +#include "ByteCode/State.h" #include "ExprConstShared.h" -#include "Interp/Context.h" -#include "Interp/Frame.h" -#include "Interp/State.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -12833,6 +12833,54 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, Success(Val.isZero() ? 1 : 0, E); } + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: { + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success(Val.isNegative() ? 1 : 0, E); + } + + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: { + APFloat LHS(0.0); + APFloat RHS(0.0); + if (!EvaluateFloat(E->getArg(0), LHS, Info) || + !EvaluateFloat(E->getArg(1), RHS, Info)) + return false; + + return Success( + [&] { + switch (BuiltinOp) { + case Builtin::BI__builtin_isgreater: + return LHS > RHS; + case Builtin::BI__builtin_isgreaterequal: + return LHS >= RHS; + case Builtin::BI__builtin_isless: + return LHS < RHS; + case Builtin::BI__builtin_islessequal: + return LHS <= RHS; + case Builtin::BI__builtin_islessgreater: { + APFloat::cmpResult cmp = LHS.compare(RHS); + return cmp == APFloat::cmpResult::cmpLessThan || + cmp == APFloat::cmpResult::cmpGreaterThan; + } + case Builtin::BI__builtin_isunordered: + return LHS.compare(RHS) == APFloat::cmpResult::cmpUnordered; + default: + llvm_unreachable("Unexpected builtin ID: Should be a floating " + "point comparison function"); + } + }() + ? 1 + : 0, + E); + } + case Builtin::BI__builtin_issignaling: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && @@ -15567,12 +15615,12 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { HandleComplexComplexDiv(A, B, C, D, ResR, ResI); } } else { - if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) - return Error(E, diag::note_expr_divide_by_zero); - ComplexValue LHS = Result; APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + RHS.getComplexIntImag() * RHS.getComplexIntImag(); + if (Den.isZero()) + return Error(E, diag::note_expr_divide_by_zero); + Result.getComplexIntReal() = (LHS.getComplexIntReal() * RHS.getComplexIntReal() + LHS.getComplexIntImag() * RHS.getComplexIntImag()) / Den; diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index f8f80c8c2515755..565f1e05710c879 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1090,6 +1090,7 @@ void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) { void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) { if (const TypeSourceInfo *T = FD->getFriendType()) JOS.attribute("type", createQualType(T->getType())); + attributeOnlyIfTrue("isPackExpansion", FD->isPackExpansion()); } void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index db8000e25dc7cc6..ed8d1cf1b98dd80 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -408,8 +408,6 @@ class MicrosoftCXXNameMangler { void mangleSourceName(StringRef Name); void mangleNestedName(GlobalDecl GD); - void mangleAutoReturnType(QualType T, QualifierMangleMode QMM); - private: bool isStructorDecl(const NamedDecl *ND) const { return ND == Structor || getStructor(ND) == Structor; @@ -479,11 +477,6 @@ class MicrosoftCXXNameMangler { SourceRange Range); void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals, SourceRange Range); - - void mangleAutoReturnType(const MemberPointerType *T, Qualifiers Quals); - void mangleAutoReturnType(const PointerType *T, Qualifiers Quals); - void mangleAutoReturnType(const LValueReferenceType *T, Qualifiers Quals); - void mangleAutoReturnType(const RValueReferenceType *T, Qualifiers Quals); }; } @@ -2501,57 +2494,6 @@ void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T, mangleArtificialTagType(TagTypeKind::Struct, ASMangling, {"__clang"}); } -void MicrosoftCXXNameMangler::mangleAutoReturnType(QualType T, - QualifierMangleMode QMM) { - assert(getASTContext().getLangOpts().isCompatibleWithMSVC( - LangOptions::MSVC2019) && - "Cannot mangle MSVC 2017 auto return types!"); - - if (isa(T)) { - const auto *AT = T->getContainedAutoType(); - Qualifiers Quals = T.getLocalQualifiers(); - - if (QMM == QMM_Result) - Out << '?'; - if (QMM != QMM_Drop) - mangleQualifiers(Quals, false); - Out << (AT->isDecltypeAuto() ? "_T" : "_P"); - return; - } - - T = T.getDesugaredType(getASTContext()); - Qualifiers Quals = T.getLocalQualifiers(); - - switch (QMM) { - case QMM_Drop: - case QMM_Result: - break; - case QMM_Mangle: - mangleQualifiers(Quals, false); - break; - default: - llvm_unreachable("QMM_Escape unexpected"); - } - - const Type *ty = T.getTypePtr(); - switch (ty->getTypeClass()) { - case Type::MemberPointer: - mangleAutoReturnType(cast(ty), Quals); - break; - case Type::Pointer: - mangleAutoReturnType(cast(ty), Quals); - break; - case Type::LValueReference: - mangleAutoReturnType(cast(ty), Quals); - break; - case Type::RValueReference: - mangleAutoReturnType(cast(ty), Quals); - break; - default: - llvm_unreachable("Invalid type expected"); - } -} - void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM) { // Don't use the canonical types. MSVC includes things like 'const' on @@ -2965,52 +2907,17 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // can differ by their calling convention and are typically deduced. So // we make sure that this type gets mangled properly. mangleType(ResultType, Range, QMM_Result); - } else if (IsInLambda) { - if (const auto *AT = ResultType->getContainedAutoType()) { - assert(AT->getKeyword() == AutoTypeKeyword::Auto && - "should only need to mangle auto!"); - (void)AT; - Out << '?'; - mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false); - Out << '?'; - mangleSourceName(""); - Out << '@'; - } else { - Out << '@'; - } - } else if (const auto *AT = ResultType->getContainedAutoType()) { + } else if (const auto *AT = dyn_cast_or_null( + ResultType->getContainedAutoType())) { + Out << '?'; + mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false); + Out << '?'; assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType && "shouldn't need to mangle __auto_type!"); - - // If we have any pointer types with the clang address space extension - // then defer to the custom clang mangling to keep backwards - // compatibility. See `mangleType(const PointerType *T, Qualifiers Quals, - // SourceRange Range)` for details. - auto UseClangMangling = [](QualType ResultType) { - QualType T = ResultType; - while (isa(T.getTypePtr())) { - T = T->getPointeeType(); - if (T.getQualifiers().hasAddressSpace()) - return true; - } - return false; - }; - - if (getASTContext().getLangOpts().isCompatibleWithMSVC( - LangOptions::MSVC2019) && - !UseClangMangling(ResultType)) { - if (D && !D->getPrimaryTemplate()) { - Out << '@'; - } else { - mangleAutoReturnType(ResultType, QMM_Result); - } - } else { - Out << '?'; - mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false); - Out << '?'; - mangleSourceName(AT->isDecltypeAuto() ? "" : ""); - Out << '@'; - } + mangleSourceName(AT->isDecltypeAuto() ? "" : ""); + Out << '@'; + } else if (IsInLambda) { + Out << '@'; } else { if (ResultType->isVoidType()) ResultType = ResultType.getUnqualifiedType(); @@ -4313,57 +4220,6 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << '@'; } -void MicrosoftCXXNameMangler::mangleAutoReturnType(const MemberPointerType *T, - Qualifiers Quals) { - QualType PointeeType = T->getPointeeType(); - manglePointerCVQualifiers(Quals); - manglePointerExtQualifiers(Quals, PointeeType); - if (const FunctionProtoType *FPT = PointeeType->getAs()) { - Out << '8'; - mangleName(T->getClass()->castAs()->getDecl()); - mangleFunctionType(FPT, nullptr, true); - } else { - mangleQualifiers(PointeeType.getQualifiers(), true); - mangleName(T->getClass()->castAs()->getDecl()); - mangleAutoReturnType(PointeeType, QMM_Drop); - } -} - -void MicrosoftCXXNameMangler::mangleAutoReturnType(const PointerType *T, - Qualifiers Quals) { - QualType PointeeType = T->getPointeeType(); - assert(!PointeeType.getQualifiers().hasAddressSpace() && - "Unexpected address space mangling required"); - - manglePointerCVQualifiers(Quals); - manglePointerExtQualifiers(Quals, PointeeType); - - if (const FunctionProtoType *FPT = PointeeType->getAs()) { - Out << '6'; - mangleFunctionType(FPT); - } else { - mangleAutoReturnType(PointeeType, QMM_Mangle); - } -} - -void MicrosoftCXXNameMangler::mangleAutoReturnType(const LValueReferenceType *T, - Qualifiers Quals) { - QualType PointeeType = T->getPointeeType(); - assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!"); - Out << 'A'; - manglePointerExtQualifiers(Quals, PointeeType); - mangleAutoReturnType(PointeeType, QMM_Mangle); -} - -void MicrosoftCXXNameMangler::mangleAutoReturnType(const RValueReferenceType *T, - Qualifiers Quals) { - QualType PointeeType = T->getPointeeType(); - assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!"); - Out << "$$Q"; - manglePointerExtQualifiers(Quals, PointeeType); - mangleAutoReturnType(PointeeType, QMM_Mangle); -} - MicrosoftMangleContext *MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux) { diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index fbfe92318dc5eee..b748093831e3f50 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -461,6 +461,7 @@ class ODRDeclVisitor : public ConstDeclVisitor { } else { AddDecl(D->getFriendDecl()); } + Hash.AddBoolean(D->isPackExpansion()); } void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index d50d4c7028c6972..2c962253c8bea42 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -2697,6 +2697,8 @@ void TextNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { void TextNodeDumper::VisitFriendDecl(const FriendDecl *D) { if (TypeSourceInfo *T = D->getFriendType()) dumpType(T->getType()); + if (D->isPackExpansion()) + OS << "..."; } void TextNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp index 27d42a7b508562e..fdba139628d8ff0 100644 --- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp @@ -170,6 +170,13 @@ static void insertIfGlobal(const Decl &D, Globals.insert(V); } +static void insertIfLocal(const Decl &D, + llvm::DenseSet &Locals) { + if (auto *V = dyn_cast(&D)) + if (V->hasLocalStorage() && !isa(V)) + Locals.insert(V); +} + static void insertIfFunction(const Decl &D, llvm::DenseSet &Funcs) { if (auto *FD = dyn_cast(&D)) @@ -220,12 +227,14 @@ class ReferencedDeclsVisitor bool VisitDecl(Decl *D) { insertIfGlobal(*D, Referenced.Globals); + insertIfLocal(*D, Referenced.Locals); insertIfFunction(*D, Referenced.Functions); return true; } bool VisitDeclRefExpr(DeclRefExpr *E) { insertIfGlobal(*E->getDecl(), Referenced.Globals); + insertIfLocal(*E->getDecl(), Referenced.Locals); insertIfFunction(*E->getDecl(), Referenced.Functions); return true; } diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 051381edabf0b25..da7446913f7c87e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -402,9 +402,9 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) { QualType Arg0Ty = Arg0->IgnoreImplicit()->getType(); - if (Arg0Ty->isConstantArrayType()) { - const APSInt ConstArrSize = - APSInt(cast(Arg0Ty)->getSize()); + if (auto *ConstArrTy = + Finder->getASTContext().getAsConstantArrayType(Arg0Ty)) { + const APSInt ConstArrSize = APSInt(ConstArrTy->getSize()); // Check form 4: return Arg1CV && APSInt::compareValues(ConstArrSize, *Arg1CV) == 0; @@ -2664,7 +2664,7 @@ static FixItList fixVarDeclWithArray(const VarDecl *D, const ASTContext &Ctx, // Note: the code below expects the declaration to not use any type sugar like // typedef. - if (auto CAT = dyn_cast(D->getType())) { + if (auto CAT = Ctx.getAsConstantArrayType(D->getType())) { const QualType &ArrayEltT = CAT->getElementType(); assert(!ArrayEltT.isNull() && "Trying to fix a non-array type variable!"); // FIXME: support multi-dimensional arrays @@ -2797,8 +2797,7 @@ fixVariable(const VarDecl *VD, FixitStrategy::Kind K, return {}; } case FixitStrategy::Kind::Array: { - if (VD->isLocalVarDecl() && - isa(VD->getType().getCanonicalType())) + if (VD->isLocalVarDecl() && Ctx.getAsConstantArrayType(VD->getType())) return fixVariableWithArray(VD, Tracker, Ctx, Handler); DEBUG_NOTE_DECL_FAIL(VD, " : not a local const-size array"); diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 533a9fe88a21508..b0256a8ce9ed042 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -2038,8 +2038,7 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, std::pair InSameTU = isInTheSameTranslationUnit(LOffs, ROffs); if (InSameTU.first) return InSameTU.second; - // TODO: This should be unreachable, but some clients are calling this - // function before making sure LHS and RHS are in the same TU. + // This case is used by libclang: clang_isBeforeInTranslationUnit return LOffs.first < ROffs.first; } diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 35e8f79ba1bac7b..be91b85e3a816f8 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -38,8 +38,9 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { : Context.LongLongTy)) return getNaturalAlignIndirect(Ty); - return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + return (isPromotableIntegerTypeForABI(Ty) + ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) + : ABIArgInfo::getDirect()); } ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 81e6702d5de6661..34c08818dbb9ade 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -471,7 +471,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags, Options.MCOptions.Dwarf64 = CodeGenOpts.Dwarf64; Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments; Options.MCOptions.Crel = CodeGenOpts.Crel; - Options.MCOptions.X86RelaxRelocations = CodeGenOpts.RelaxELFRelocations; + Options.MCOptions.X86RelaxRelocations = CodeGenOpts.X86RelaxRelocations; Options.MCOptions.CompressDebugSections = CodeGenOpts.getCompressDebugSections(); Options.MCOptions.ABIName = TargetOpts.ABI; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1c0baeaee036321..f424ddaa175400c 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -58,6 +58,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/MatrixBuilder.h" #include "llvm/IR/MemoryModelRelaxationAnnotations.h" +#include "llvm/Support/AMDGPUAddrSpace.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ScopedPrinter.h" @@ -18919,8 +18920,6 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, Function *F = CGM.getIntrinsic(Intrin, { Src0->getType() }); return Builder.CreateCall(F, { Src0, Builder.getFalse() }); } - case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f64: - case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f32: case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_v2f16: case AMDGPU::BI__builtin_amdgcn_global_atomic_fmin_f64: case AMDGPU::BI__builtin_amdgcn_global_atomic_fmax_f64: @@ -18932,18 +18931,11 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, Intrinsic::ID IID; llvm::Type *ArgTy = llvm::Type::getDoubleTy(getLLVMContext()); switch (BuiltinID) { - case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f32: - ArgTy = llvm::Type::getFloatTy(getLLVMContext()); - IID = Intrinsic::amdgcn_global_atomic_fadd; - break; case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_v2f16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getHalfTy(getLLVMContext()), 2); IID = Intrinsic::amdgcn_global_atomic_fadd; break; - case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f64: - IID = Intrinsic::amdgcn_global_atomic_fadd; - break; case AMDGPU::BI__builtin_amdgcn_global_atomic_fmin_f64: IID = Intrinsic::amdgcn_global_atomic_fmin; break; @@ -19366,7 +19358,9 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2bf16: case AMDGPU::BI__builtin_amdgcn_ds_faddf: case AMDGPU::BI__builtin_amdgcn_ds_fminf: - case AMDGPU::BI__builtin_amdgcn_ds_fmaxf: { + case AMDGPU::BI__builtin_amdgcn_ds_fmaxf: + case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f32: + case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f64: { llvm::AtomicRMWInst::BinOp BinOp; switch (BuiltinID) { case AMDGPU::BI__builtin_amdgcn_atomic_inc32: @@ -19382,6 +19376,8 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_f32: case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2f16: case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2bf16: + case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f32: + case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f64: BinOp = llvm::AtomicRMWInst::FAdd; break; case AMDGPU::BI__builtin_amdgcn_ds_fminf: @@ -19416,9 +19412,14 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, ProcessOrderScopeAMDGCN(EmitScalarExpr(E->getArg(2)), EmitScalarExpr(E->getArg(3)), AO, SSID); } else { - // The ds_atomic_fadd_* builtins do not have syncscope/order arguments. - SSID = llvm::SyncScope::System; - AO = AtomicOrdering::SequentiallyConsistent; + // Most of the builtins do not have syncscope/order arguments. For DS + // atomics the scope doesn't really matter, as they implicitly operate at + // workgroup scope. + // + // The global/flat cases need to use agent scope to consistently produce + // the native instruction instead of a cmpxchg expansion. + SSID = getLLVMContext().getOrInsertSyncScopeID("agent"); + AO = AtomicOrdering::Monotonic; // The v2bf16 builtin uses i16 instead of a natural bfloat type. if (BuiltinID == AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2bf16) { @@ -19432,6 +19433,20 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, Builder.CreateAtomicRMW(BinOp, Ptr, Val, AO, SSID); if (Volatile) RMW->setVolatile(true); + + unsigned AddrSpace = Ptr.getType()->getAddressSpace(); + if (AddrSpace != llvm::AMDGPUAS::LOCAL_ADDRESS) { + // Most targets require "amdgpu.no.fine.grained.memory" to emit the native + // instruction for flat and global operations. + llvm::MDTuple *EmptyMD = MDNode::get(getLLVMContext(), {}); + RMW->setMetadata("amdgpu.no.fine.grained.memory", EmptyMD); + + // Most targets require "amdgpu.ignore.denormal.mode" to emit the native + // instruction, but this only matters for float fadd. + if (BinOp == llvm::AtomicRMWInst::FAdd && Val->getType()->isFloatTy()) + RMW->setMetadata("amdgpu.ignore.denormal.mode", EmptyMD); + } + return Builder.CreateBitCast(RMW, OrigTy); } case AMDGPU::BI__builtin_amdgcn_s_sendmsg_rtn: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 0672861790633bb..48d9a3b8a5acb3b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -42,6 +42,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -65,6 +66,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//===--------------------------------------------------------------------===// +// Defines for metadata +//===--------------------------------------------------------------------===// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x0000, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0xffff +}; + //===--------------------------------------------------------------------===// // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// @@ -3288,22 +3305,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0xFFFF) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { - TypeKind = 0; + TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); + // Follow suggestion from discussion of issue 64100. + // So we can write the exact amount of bits in TypeName after '\0' + // making it .'\0'.<32-bit width>. + if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert(getContext().getTypeSize(T) > 0 && + " non positive amount of bits in __BitInt type"); + assert(getContext().getTypeSize(T) <= 0xFFFFFFFF && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; + } } else if (T->isFloatingType()) { - TypeKind = 1; + TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3314,6 +3349,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(), StringRef(), std::nullopt, Buffer, std::nullopt); + if (IsBitInt) { + // The Structure is: 0 to end the string, 32 bit unsigned integer in target + // endianness, zero. + char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'}; + const auto *EIT = T->castAs(); + uint32_t Bits = EIT->getNumBits(); + llvm::support::endian::write32(S + 1, Bits, + getTarget().isBigEndian() + ? llvm::endianness::big + : llvm::endianness::little); + StringRef Str = StringRef(S, sizeof(S) / sizeof(decltype(S[0]))); + Buffer.append(Str); + } + llvm::Constant *Components[] = { Builder.getInt16(TypeKind), Builder.getInt16(TypeInfo), llvm::ConstantDataArray::getString(getLLVMContext(), Buffer) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 6eac2b4c54e1ba3..84392745ea6144d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -24,7 +24,6 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" -#include "clang/AST/ParentMapContext.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/CodeGenOptions.h" @@ -196,24 +195,13 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { if (!Op.mayHaveIntegerOverflow()) return true; - const UnaryOperator *UO = dyn_cast(Op.E); - - if (UO && UO->getOpcode() == UO_Minus && - Ctx.getLangOpts().isOverflowPatternExcluded( - LangOptions::OverflowPatternExclusionKind::NegUnsignedConst) && - UO->isIntegerConstantExpr(Ctx)) - return true; - // If a unary op has a widened operand, the op cannot overflow. - if (UO) + if (const auto *UO = dyn_cast(Op.E)) return !UO->canOverflow(); // We usually don't need overflow checks for binops with widened operands. // Multiplication with promoted unsigned operands is a special case. const auto *BO = cast(Op.E); - if (BO->hasExcludedOverflowPattern()) - return true; - auto OptionalLHSTy = getUnwidenedIntegerType(Ctx, BO->getLHS()); if (!OptionalLHSTy) return false; @@ -2778,26 +2766,6 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior( llvm_unreachable("Unknown SignedOverflowBehaviorTy"); } -/// For the purposes of overflow pattern exclusion, does this match the -/// "while(i--)" pattern? -static bool matchesPostDecrInWhile(const UnaryOperator *UO, bool isInc, - bool isPre, ASTContext &Ctx) { - if (isInc || isPre) - return false; - - // -fsanitize-overflow-pattern-exclusion=post-decr-while - if (!Ctx.getLangOpts().isOverflowPatternExcluded( - LangOptions::OverflowPatternExclusionKind::PostDecrInWhile)) - return false; - - // all Parents (usually just one) must be a WhileStmt - for (const auto &Parent : Ctx.getParentMapContext().getParents(*UO)) - if (!Parent.get()) - return false; - - return true; -} - namespace { /// Handles check and update for lastprivate conditional variables. class OMPLastprivateConditionalUpdateRAII { @@ -2909,10 +2877,6 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } else if (type->isIntegerType()) { QualType promotedType; bool canPerformLossyDemotionCheck = false; - - bool excludeOverflowPattern = - matchesPostDecrInWhile(E, isInc, isPre, CGF.getContext()); - if (CGF.getContext().isPromotableIntegerType(type)) { promotedType = CGF.getContext().getPromotedIntegerType(type); assert(promotedType != type && "Shouldn't promote to the same type."); @@ -2972,8 +2936,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } else if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) { value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); } else if (E->canOverflow() && type->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && - !excludeOverflowPattern) { + CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) { value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec( E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts()))); } else { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 8c5e4aa9c037e2b..34120486996fb17 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -9588,15 +9588,18 @@ static void genMapInfo(const OMPExecutableDirective &D, CodeGenFunction &CGF, genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet); } -static void emitNumTeamsForBareTargetDirective( - CodeGenFunction &CGF, const OMPExecutableDirective &D, - llvm::SmallVectorImpl &NumTeams) { - const auto *C = D.getSingleClause(); - assert(!C->varlist_empty() && "ompx_bare requires explicit num_teams"); - CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); - for (auto *E : C->getNumTeams()) { +template +static void +emitClauseForBareTargetDirective(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + llvm::SmallVectorImpl &Values) { + const auto *C = D.getSingleClause(); + assert(!C->varlist_empty() && + "ompx_bare requires explicit num_teams and thread_limit"); + CodeGenFunction::RunCleanupsScope Scope(CGF); + for (auto *E : C->varlist()) { llvm::Value *V = CGF.EmitScalarExpr(E); - NumTeams.push_back( + Values.push_back( CGF.Builder.CreateIntCast(V, CGF.Int32Ty, /*isSigned=*/true)); } } @@ -9672,14 +9675,18 @@ static void emitTargetCallKernelLaunch( bool IsBare = D.hasClausesOfKind(); SmallVector NumTeams; - if (IsBare) - emitNumTeamsForBareTargetDirective(CGF, D, NumTeams); - else + SmallVector NumThreads; + if (IsBare) { + emitClauseForBareTargetDirective(CGF, D, NumTeams); + emitClauseForBareTargetDirective(CGF, D, + NumThreads); + } else { NumTeams.push_back(OMPRuntime->emitNumTeamsForTargetDirective(CGF, D)); + NumThreads.push_back( + OMPRuntime->emitNumThreadsForTargetDirective(CGF, D)); + } llvm::Value *DeviceID = emitDeviceID(Device, CGF); - llvm::Value *NumThreads = - OMPRuntime->emitNumThreadsForTargetDirective(CGF, D); llvm::Value *RTLoc = OMPRuntime->emitUpdateLocation(CGF, D.getBeginLoc()); llvm::Value *NumIterations = OMPRuntime->emitTargetNumIterationsCall(CGF, D, SizeEmitter); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 6d11bd17d0a5f5d..0b61ef0f89989ce 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1220,8 +1220,14 @@ void CodeGenModule::Release() { (LangOpts.PointerAuthInitFiniAddressDiscrimination << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINIADDRDISC) | (LangOpts.PointerAuthELFGOT - << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT); - static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT == + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT) | + (LangOpts.PointerAuthIndirectGotos + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOTOS) | + (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_TYPEINFOVPTRDISCR) | + (LangOpts.PointerAuthFunctionTypeDiscrimination + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_FPTRTYPEDISCR); + static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_FPTRTYPEDISCR == AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST, "Update when new enum items are defined"); if (PAuthABIVersion != 0) { diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index e4155810963eb81..989e46f4b66a7d6 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -217,8 +217,9 @@ ABIArgInfo AIXABIInfo::classifyArgumentType(QualType Ty) const { /*Realign*/ TyAlign > CCAlign); } - return (isPromotableTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + return (isPromotableTypeForABI(Ty) + ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) + : ABIArgInfo::getDirect()); } CharUnits AIXABIInfo::getParamTypeAlignment(QualType Ty) const { @@ -891,8 +892,9 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { /*Realign=*/TyAlign > ABIAlign); } - return (isPromotableTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + return (isPromotableTypeForABI(Ty) + ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) + : ABIArgInfo::getDirect()); } ABIArgInfo diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 5b95019c25cab67..e12416e51f8d248 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2271,7 +2271,8 @@ bool Driver::HandleImmediateArgs(Compilation &C) { return false; } - auto initializeTargets = [&]() { + if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) { + ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs()); const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs())); // The 'Darwin' toolchain is initialized only when its arguments are // computed. Get the default arguments for OFK_None to ensure that @@ -2281,12 +2282,6 @@ bool Driver::HandleImmediateArgs(Compilation &C) { // FIXME: For some more esoteric targets the default toolchain is not the // correct one. C.getArgsForToolChain(&TC, Triple.getArchName(), Action::OFK_None); - return Triple; - }; - - if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) { - ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs()); - const llvm::Triple Triple = initializeTargets(); RegisterEffectiveTriple TripleRAII(TC, Triple); switch (RLT) { case ToolChain::RLT_CompilerRT: @@ -2330,9 +2325,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) { } if (C.getArgs().hasArg(options::OPT_print_target_triple)) { - initializeTargets(); - llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs())); - llvm::outs() << Triple.getTriple() << "\n"; + llvm::outs() << TC.getTripleString() << "\n"; return false; } diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index a63ee944fd1bb41..1fd870b72286e55 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -119,10 +119,6 @@ static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors); -static int parseOverflowPatternExclusionValues(const Driver &D, - const llvm::opt::Arg *A, - bool DiagnoseErrors); - /// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid /// components. Returns OR of members of \c BinaryMetadataFeature enumeration. static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A, @@ -792,13 +788,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, << "fsanitize-trap=cfi"; } - for (const auto *Arg : - Args.filtered(options::OPT_fsanitize_overflow_pattern_exclusion_EQ)) { - Arg->claim(); - OverflowPatternExclusions |= - parseOverflowPatternExclusionValues(D, Arg, DiagnoseErrors); - } - // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the // enabled sanitizers. for (const auto *Arg : Args) { @@ -1252,10 +1241,6 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-system-ignorelist=", SystemIgnorelistFiles); - if (OverflowPatternExclusions) - Args.AddAllArgs(CmdArgs, - options::OPT_fsanitize_overflow_pattern_exclusion_EQ); - if (MsanTrackOrigins) CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" + Twine(MsanTrackOrigins))); @@ -1441,28 +1426,6 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, return Kinds; } -static int parseOverflowPatternExclusionValues(const Driver &D, - const llvm::opt::Arg *A, - bool DiagnoseErrors) { - int Exclusions = 0; - for (int i = 0, n = A->getNumValues(); i != n; ++i) { - const char *Value = A->getValue(i); - int E = - llvm::StringSwitch(Value) - .Case("none", LangOptionsBase::None) - .Case("all", LangOptionsBase::All) - .Case("add-overflow-test", LangOptionsBase::AddOverflowTest) - .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst) - .Case("post-decr-while", LangOptionsBase::PostDecrInWhile) - .Default(0); - if (E == 0) - D.Diag(clang::diag::err_drv_unsupported_option_argument) - << A->getSpelling() << Value; - Exclusions |= E; - } - return Exclusions; -} - int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors) { assert(A->getOption().matches(options::OPT_fsanitize_coverage) || diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 013709999155217..0e8577b1115e38e 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -9,6 +9,7 @@ #include "clang/Driver/ToolChain.h" #include "ToolChains/Arch/AArch64.h" #include "ToolChains/Arch/ARM.h" +#include "ToolChains/Arch/RISCV.h" #include "ToolChains/Clang.h" #include "ToolChains/CommonArgs.h" #include "ToolChains/Flang.h" @@ -44,6 +45,7 @@ #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/AArch64TargetParser.h" +#include "llvm/TargetParser/RISCVISAInfo.h" #include "llvm/TargetParser/TargetParser.h" #include "llvm/TargetParser/Triple.h" #include @@ -268,6 +270,19 @@ static void getARMMultilibFlags(const Driver &D, } } +static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + Multilib::flags_list &Result) { + std::string Arch = riscv::getRISCVArch(Args, Triple); + // Canonicalize arch for easier matching + auto ISAInfo = llvm::RISCVISAInfo::parseArchString( + Arch, /*EnableExperimentalExtensions*/ true); + if (!llvm::errorToBool(ISAInfo.takeError())) + Result.push_back("-march=" + (*ISAInfo)->toString()); + + Result.push_back(("-mabi=" + riscv::getRISCVABI(Args, Triple)).str()); +} + Multilib::flags_list ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { using namespace clang::driver::options; @@ -288,6 +303,10 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { case llvm::Triple::thumbeb: getARMMultilibFlags(D, Triple, Args, Result); break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + getRISCVMultilibFlags(D, Triple, Args, Result); + break; default: break; } diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 149a31f58e75d21..6935904a24edbfd 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -95,69 +95,42 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, CPUFastVectorUnaligned = true; } - // Handle features corresponding to "-ffixed-X" options - if (Args.hasArg(options::OPT_ffixed_x1)) - Features.push_back("+reserve-x1"); - if (Args.hasArg(options::OPT_ffixed_x2)) - Features.push_back("+reserve-x2"); - if (Args.hasArg(options::OPT_ffixed_x3)) - Features.push_back("+reserve-x3"); - if (Args.hasArg(options::OPT_ffixed_x4)) - Features.push_back("+reserve-x4"); - if (Args.hasArg(options::OPT_ffixed_x5)) - Features.push_back("+reserve-x5"); - if (Args.hasArg(options::OPT_ffixed_x6)) - Features.push_back("+reserve-x6"); - if (Args.hasArg(options::OPT_ffixed_x7)) - Features.push_back("+reserve-x7"); - if (Args.hasArg(options::OPT_ffixed_x8)) - Features.push_back("+reserve-x8"); - if (Args.hasArg(options::OPT_ffixed_x9)) - Features.push_back("+reserve-x9"); - if (Args.hasArg(options::OPT_ffixed_x10)) - Features.push_back("+reserve-x10"); - if (Args.hasArg(options::OPT_ffixed_x11)) - Features.push_back("+reserve-x11"); - if (Args.hasArg(options::OPT_ffixed_x12)) - Features.push_back("+reserve-x12"); - if (Args.hasArg(options::OPT_ffixed_x13)) - Features.push_back("+reserve-x13"); - if (Args.hasArg(options::OPT_ffixed_x14)) - Features.push_back("+reserve-x14"); - if (Args.hasArg(options::OPT_ffixed_x15)) - Features.push_back("+reserve-x15"); - if (Args.hasArg(options::OPT_ffixed_x16)) - Features.push_back("+reserve-x16"); - if (Args.hasArg(options::OPT_ffixed_x17)) - Features.push_back("+reserve-x17"); - if (Args.hasArg(options::OPT_ffixed_x18)) - Features.push_back("+reserve-x18"); - if (Args.hasArg(options::OPT_ffixed_x19)) - Features.push_back("+reserve-x19"); - if (Args.hasArg(options::OPT_ffixed_x20)) - Features.push_back("+reserve-x20"); - if (Args.hasArg(options::OPT_ffixed_x21)) - Features.push_back("+reserve-x21"); - if (Args.hasArg(options::OPT_ffixed_x22)) - Features.push_back("+reserve-x22"); - if (Args.hasArg(options::OPT_ffixed_x23)) - Features.push_back("+reserve-x23"); - if (Args.hasArg(options::OPT_ffixed_x24)) - Features.push_back("+reserve-x24"); - if (Args.hasArg(options::OPT_ffixed_x25)) - Features.push_back("+reserve-x25"); - if (Args.hasArg(options::OPT_ffixed_x26)) - Features.push_back("+reserve-x26"); - if (Args.hasArg(options::OPT_ffixed_x27)) - Features.push_back("+reserve-x27"); - if (Args.hasArg(options::OPT_ffixed_x28)) - Features.push_back("+reserve-x28"); - if (Args.hasArg(options::OPT_ffixed_x29)) - Features.push_back("+reserve-x29"); - if (Args.hasArg(options::OPT_ffixed_x30)) - Features.push_back("+reserve-x30"); - if (Args.hasArg(options::OPT_ffixed_x31)) - Features.push_back("+reserve-x31"); +// Handle features corresponding to "-ffixed-X" options +#define RESERVE_REG(REG) \ + if (Args.hasArg(options::OPT_ffixed_##REG)) \ + Features.push_back("+reserve-" #REG); + RESERVE_REG(x1) + RESERVE_REG(x2) + RESERVE_REG(x3) + RESERVE_REG(x4) + RESERVE_REG(x5) + RESERVE_REG(x6) + RESERVE_REG(x7) + RESERVE_REG(x8) + RESERVE_REG(x9) + RESERVE_REG(x10) + RESERVE_REG(x11) + RESERVE_REG(x12) + RESERVE_REG(x13) + RESERVE_REG(x14) + RESERVE_REG(x15) + RESERVE_REG(x16) + RESERVE_REG(x17) + RESERVE_REG(x18) + RESERVE_REG(x19) + RESERVE_REG(x20) + RESERVE_REG(x21) + RESERVE_REG(x22) + RESERVE_REG(x23) + RESERVE_REG(x24) + RESERVE_REG(x25) + RESERVE_REG(x26) + RESERVE_REG(x27) + RESERVE_REG(x28) + RESERVE_REG(x29) + RESERVE_REG(x30) + RESERVE_REG(x31) +#undef RESERVE_REG // -mrelax is default, unless -mno-relax is specified. if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) { diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp index ae1a4ba7882627f..5a1fedbec06adfa 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp @@ -179,6 +179,11 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, Features.push_back("-hard-quad-float"); } + if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) { + if (A->getOption().matches(options::OPT_mv8plus)) + Features.push_back("+v8plus"); + } + if (Args.hasArg(options::OPT_ffixed_g1)) Features.push_back("+reserve-g1"); diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index 102d12700229e68..0f5f32f3f8f495a 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -218,17 +218,19 @@ static std::string computeBaseSysRoot(const Driver &D, void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) { DetectedMultilibs Result; - if (isRISCVBareMetal(Triple)) { + // Look for a multilib.yaml before trying target-specific hardwired logic. + // If it exists, always do what it specifies. + llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple)); + llvm::sys::path::append(MultilibPath, MultilibFilename); + if (D.getVFS().exists(MultilibPath)) { + findMultilibsFromYAML(*this, D, MultilibPath, Args, Result); + SelectedMultilibs = Result.SelectedMultilibs; + Multilibs = Result.Multilibs; + } else if (isRISCVBareMetal(Triple)) { if (findRISCVMultilibs(D, Triple, Args, Result)) { SelectedMultilibs = Result.SelectedMultilibs; Multilibs = Result.Multilibs; } - } else { - llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple)); - llvm::sys::path::append(MultilibPath, MultilibFilename); - findMultilibsFromYAML(*this, D, MultilibPath, Args, Result); - SelectedMultilibs = Result.SelectedMultilibs; - Multilibs = Result.Multilibs; } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f2bc11839edd4d0..a8606a866bdff64 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2104,6 +2104,9 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, CmdArgs.push_back("-mabi=vec-extabi"); } + if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true)) + CmdArgs.push_back("-disable-red-zone"); + ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); if (FloatABI == ppc::FloatABI::Soft) { // Floating point operations and argument passing are soft. @@ -2123,42 +2126,6 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, } } -static void SetRISCVSmallDataLimit(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - const Driver &D = TC.getDriver(); - const llvm::Triple &Triple = TC.getTriple(); - // Default small data limitation is eight. - const char *SmallDataLimit = "8"; - // Get small data limitation. - if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, - options::OPT_fPIC)) { - // Not support linker relaxation for PIC. - SmallDataLimit = "0"; - if (Args.hasArg(options::OPT_G)) { - D.Diag(diag::warn_drv_unsupported_sdata); - } - } else if (Args.getLastArgValue(options::OPT_mcmodel_EQ) - .equals_insensitive("large") && - (Triple.getArch() == llvm::Triple::riscv64)) { - // Not support linker relaxation for RV64 with large code model. - SmallDataLimit = "0"; - if (Args.hasArg(options::OPT_G)) { - D.Diag(diag::warn_drv_unsupported_sdata); - } - } else if (Triple.isAndroid()) { - // GP relaxation is not supported on Android. - SmallDataLimit = "0"; - if (Args.hasArg(options::OPT_G)) { - D.Diag(diag::warn_drv_unsupported_sdata); - } - } else if (Arg *A = Args.getLastArg(options::OPT_G)) { - SmallDataLimit = A->getValue(); - } - // Forward the -msmall-data-limit= option. - CmdArgs.push_back("-msmall-data-limit"); - CmdArgs.push_back(SmallDataLimit); -} - void Clang::AddRISCVTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const llvm::Triple &Triple = getToolChain().getTriple(); @@ -2167,7 +2134,10 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args, CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); - SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs); + if (Arg *A = Args.getLastArg(options::OPT_G)) { + CmdArgs.push_back("-msmall-data-limit"); + CmdArgs.push_back(A->getValue()); + } if (!Args.hasFlag(options::OPT_mimplicit_float, options::OPT_mno_implicit_float, true)) @@ -2582,6 +2552,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, bool TakeNextArg = false; const llvm::Triple &Triple = C.getDefaultToolChain().getTriple(); + bool IsELF = Triple.isOSBinFormatELF(); bool Crel = false, ExperimentalCrel = false; bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations(); bool UseNoExecStack = false; @@ -2620,11 +2591,29 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, Value == "-mbig-obj") continue; // LLVM handles bigobj automatically + auto Equal = Value.split('='); + auto checkArg = [&](bool ValidTarget, + std::initializer_list Set) { + if (!ValidTarget) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << (Twine("-Wa,") + Equal.first + "=").str() + << Triple.getTriple(); + } else if (!llvm::is_contained(Set, Equal.second)) { + D.Diag(diag::err_drv_unsupported_option_argument) + << (Twine("-Wa,") + Equal.first + "=").str() << Equal.second; + } + }; switch (C.getDefaultToolChain().getArch()) { default: break; case llvm::Triple::x86: case llvm::Triple::x86_64: + if (Equal.first == "-mrelax-relocations" || + Equal.first == "--mrelax-relocations") { + UseRelaxRelocations = Equal.second == "yes"; + checkArg(IsELF, {"yes", "no"}); + continue; + } if (Value == "-msse2avx") { CmdArgs.push_back("-msse2avx"); continue; @@ -2641,11 +2630,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, case llvm::Triple::thumbeb: case llvm::Triple::arm: case llvm::Triple::armeb: - if (Value.starts_with("-mimplicit-it=")) { + if (Equal.first == "-mimplicit-it") { // Only store the value; the last value set takes effect. - ImplicitIt = Value.split("=").second; - if (CheckARMImplicitITArg(ImplicitIt)) - continue; + ImplicitIt = Equal.second; + checkArg(true, {"always", "never", "arm", "thumb"}); + continue; } if (Value == "-mthumb") // -mthumb has already been processed in ComputeLLVMTriple() @@ -2719,12 +2708,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, Crel = false; } else if (Value == "--allow-experimental-crel") { ExperimentalCrel = true; - } else if (Value == "-mrelax-relocations=yes" || - Value == "--mrelax-relocations=yes") { - UseRelaxRelocations = true; - } else if (Value == "-mrelax-relocations=no" || - Value == "--mrelax-relocations=no") { - UseRelaxRelocations = false; } else if (Value.starts_with("-I")) { CmdArgs.push_back(Value.data()); // We need to consume the next argument if the current arg is a plain @@ -7769,9 +7752,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fgpu_default_stream_EQ); } - Args.AddAllArgs(CmdArgs, - options::OPT_fsanitize_overflow_pattern_exclusion_EQ); - Args.AddLastArg(CmdArgs, options::OPT_foffload_uniform_block, options::OPT_fno_offload_uniform_block); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 1cba3e1220264ab..320d2901da06ed5 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1143,8 +1143,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, addMachineOutlinerArgs(D, Args, CmdArgs, ToolChain.getEffectiveTriple(), /*IsLTO=*/true, PluginOptPrefix); + bool Crel = false; for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA)) { - bool Crel = false; for (StringRef V : A->getValues()) { if (V == "--crel") Crel = true; @@ -1154,13 +1154,13 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, continue; A->claim(); } - if (Crel) { - if (Triple.isOSBinFormatELF() && !Triple.isMIPS()) { - CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "-crel")); - } else { - D.Diag(diag::err_drv_unsupported_opt_for_target) - << "-Wa,--crel" << D.getTargetTriple(); - } + } + if (Crel) { + if (Triple.isOSBinFormatELF() && !Triple.isMIPS()) { + CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "-crel")); + } else { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << "-Wa,--crel" << D.getTargetTriple(); } } } diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp index f32a23f111e4bf9..1b707376dea819c 100644 --- a/clang/lib/Driver/ToolChains/HIPUtility.cpp +++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp @@ -52,13 +52,16 @@ static std::string normalizeForBundler(const llvm::Triple &T, // input object or archive files. class HIPUndefinedFatBinSymbols { public: - HIPUndefinedFatBinSymbols(const Compilation &C) - : C(C), DiagID(C.getDriver().getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Error collecting HIP undefined fatbin symbols: %0")), + HIPUndefinedFatBinSymbols(const Compilation &C, + const llvm::opt::ArgList &Args_) + : C(C), Args(Args_), + DiagID(C.getDriver().getDiags().getCustomDiagID( + DiagnosticsEngine::Error, + "Error collecting HIP undefined fatbin symbols: %0")), Quiet(C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)), Verbose(C.getArgs().hasArg(options::OPT_v)) { populateSymbols(); + processStaticLibraries(); if (Verbose) { for (const auto &Name : FatBinSymbols) llvm::errs() << "Found undefined HIP fatbin symbol: " << Name << "\n"; @@ -76,8 +79,70 @@ class HIPUndefinedFatBinSymbols { return GPUBinHandleSymbols; } + // Collect symbols from static libraries specified by -l options. + void processStaticLibraries() { + llvm::SmallVector LibNames; + llvm::SmallVector LibPaths; + llvm::SmallVector ExactLibNames; + llvm::Triple Triple(C.getDriver().getTargetTriple()); + bool IsMSVC = Triple.isWindowsMSVCEnvironment(); + llvm::StringRef Ext = IsMSVC ? ".lib" : ".a"; + + for (const auto *Arg : Args.filtered(options::OPT_l)) { + llvm::StringRef Value = Arg->getValue(); + if (Value.starts_with(":")) + ExactLibNames.push_back(Value.drop_front()); + else + LibNames.push_back(Value); + } + for (const auto *Arg : Args.filtered(options::OPT_L)) { + auto Path = Arg->getValue(); + LibPaths.push_back(Path); + if (Verbose) + llvm::errs() << "HIP fatbin symbol search uses library path: " << Path + << "\n"; + } + + auto ProcessLib = [&](llvm::StringRef LibName, bool IsExact) { + llvm::SmallString<256> FullLibName( + IsExact ? Twine(LibName).str() + : IsMSVC ? (Twine(LibName) + Ext).str() + : (Twine("lib") + LibName + Ext).str()); + + bool Found = false; + for (const auto Path : LibPaths) { + llvm::SmallString<256> FullPath = Path; + llvm::sys::path::append(FullPath, FullLibName); + + if (llvm::sys::fs::exists(FullPath)) { + if (Verbose) + llvm::errs() << "HIP fatbin symbol search found library: " + << FullPath << "\n"; + auto BufferOrErr = llvm::MemoryBuffer::getFile(FullPath); + if (!BufferOrErr) { + errorHandler(llvm::errorCodeToError(BufferOrErr.getError())); + continue; + } + processInput(BufferOrErr.get()->getMemBufferRef()); + Found = true; + break; + } + } + if (!Found && Verbose) + llvm::errs() << "HIP fatbin symbol search could not find library: " + << FullLibName << "\n"; + }; + + for (const auto LibName : ExactLibNames) + ProcessLib(LibName, true); + + for (const auto LibName : LibNames) + ProcessLib(LibName, false); + } + private: const Compilation &C; + const llvm::opt::ArgList &Args; unsigned DiagID; bool Quiet; bool Verbose; @@ -301,7 +366,7 @@ void HIP::constructGenerateObjFileFromHIPFatBinary( auto HostTriple = C.getSingleOffloadToolChain()->getTriple(); - HIPUndefinedFatBinSymbols Symbols(C); + HIPUndefinedFatBinSymbols Symbols(C, Args); std::string PrimaryHipFatbinSymbol; std::string PrimaryGpuBinHandleSymbol; diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index 8286e3be21803f2..ad44c2cfcd8115f 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -283,14 +283,6 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, DAL->append(A); } - // Add default validator version if not set. - // TODO: remove this once read validator version from validator. - if (!DAL->hasArg(options::OPT_dxil_validator_version)) { - const StringRef DefaultValidatorVer = "1.7"; - DAL->AddSeparateArg(nullptr, - Opts.getOption(options::OPT_dxil_validator_version), - DefaultValidatorVer); - } if (!DAL->hasArg(options::OPT_O_Group)) { DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), "3"); } diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 2b9b391c19c9fd0..3de45b00b4d00fd 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -170,6 +170,9 @@ bool types::isAcceptedByFlang(ID Id) { case TY_LLVM_IR: case TY_LLVM_BC: return true; + case TY_PP_CUDA: + case TY_CUDA: + return true; } } diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 6e56ee5b573f66a..1f8029cbd39ad25 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -104,6 +104,10 @@ Object serializePlatform(const Triple &T) { Object Platform; Platform["architecture"] = T.getArchName(); Platform["vendor"] = T.getVendorName(); + + if (!T.getEnvironmentName().empty()) + Platform["environment"] = T.getEnvironmentName(); + Platform["operatingSystem"] = serializeOperatingSystem(T); return Platform; } @@ -171,22 +175,25 @@ std::optional serializeAvailability(const AvailabilityInfo &Avail) { UnconditionallyDeprecated["isUnconditionallyDeprecated"] = true; AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated)); } - Object Availability; - - Availability["domain"] = Avail.Domain; - - if (Avail.isUnavailable()) { - Availability["isUnconditionallyUnavailable"] = true; - } else { - serializeObject(Availability, "introduced", - serializeSemanticVersion(Avail.Introduced)); - serializeObject(Availability, "deprecated", - serializeSemanticVersion(Avail.Deprecated)); - serializeObject(Availability, "obsoleted", - serializeSemanticVersion(Avail.Obsoleted)); + + if (Avail.Domain.str() != "") { + Object Availability; + Availability["domain"] = Avail.Domain; + + if (Avail.isUnavailable()) { + Availability["isUnconditionallyUnavailable"] = true; + } else { + serializeObject(Availability, "introduced", + serializeSemanticVersion(Avail.Introduced)); + serializeObject(Availability, "deprecated", + serializeSemanticVersion(Avail.Deprecated)); + serializeObject(Availability, "obsoleted", + serializeSemanticVersion(Avail.Obsoleted)); + } + + AvailabilityArray.emplace_back(std::move(Availability)); } - AvailabilityArray.emplace_back(std::move(Availability)); return AvailabilityArray; } diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 43d246b7f824198..46dafad65863dcf 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1427,6 +1427,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { switch (Style.RequiresClausePosition) { case FormatStyle::RCPS_OwnLine: case FormatStyle::RCPS_WithFollowing: + case FormatStyle::RCPS_OwnLineWithBrace: return CurrentState.Indent; default: break; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 5358b35c19de25e..97fac41cdd30088 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -540,6 +540,7 @@ struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::RequiresClausePositionStyle &Value) { IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine); + IO.enumCase(Value, "OwnLineWithBrace", FormatStyle::RCPS_OwnLineWithBrace); IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding); IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing); IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine); @@ -1904,7 +1905,6 @@ FormatStyle getGNUStyle() { Style.Cpp11BracedListStyle = false; Style.FixNamespaceComments = false; Style.SpaceBeforeParens = FormatStyle::SBPO_Always; - Style.Standard = FormatStyle::LS_Cpp03; return Style; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 9f79fa9fc516ca6..9d4204655b8ed6e 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5681,6 +5681,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, if (Right.is(TT_RequiresClause)) { switch (Style.RequiresClausePosition) { case FormatStyle::RCPS_OwnLine: + case FormatStyle::RCPS_OwnLineWithBrace: case FormatStyle::RCPS_WithFollowing: return true; default: @@ -5699,11 +5700,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, (Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave && Right.NewlinesBefore > 0); } - if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) { + if (Left.ClosesRequiresClause) { switch (Style.RequiresClausePosition) { case FormatStyle::RCPS_OwnLine: case FormatStyle::RCPS_WithPreceding: - return true; + return Right.isNot(tok::semi); + case FormatStyle::RCPS_OwnLineWithBrace: + return !Right.isOneOf(tok::semi, tok::l_brace); default: break; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5a5f5cb79a12f2b..e3911c281985b72 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4267,19 +4267,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } - if (auto *A = Args.getLastArg(OPT_fsanitize_overflow_pattern_exclusion_EQ)) { - for (int i = 0, n = A->getNumValues(); i != n; ++i) { - Opts.OverflowPatternExclusionMask |= - llvm::StringSwitch(A->getValue(i)) - .Case("none", LangOptionsBase::None) - .Case("all", LangOptionsBase::All) - .Case("add-overflow-test", LangOptionsBase::AddOverflowTest) - .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst) - .Case("post-decr-while", LangOptionsBase::PostDecrInWhile) - .Default(0); - } - } - // Parse -fsanitize= arguments. parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), Diags, Opts.Sanitize); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 8e62461d8a1818b..4f2856dd2247f8f 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -765,6 +765,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, // C++26 features supported in earlier language modes. Builder.defineMacro("__cpp_pack_indexing", "202311L"); Builder.defineMacro("__cpp_deleted_function", "202403L"); + Builder.defineMacro("__cpp_variadic_friend", "202403L"); if (LangOpts.Char8) Builder.defineMacro("__cpp_char8_t", "202207L"); diff --git a/clang/lib/Frontend/Rewrite/FixItRewriter.cpp b/clang/lib/Frontend/Rewrite/FixItRewriter.cpp index 567bac576adb40a..44dfaf20eae73f0 100644 --- a/clang/lib/Frontend/Rewrite/FixItRewriter.cpp +++ b/clang/lib/Frontend/Rewrite/FixItRewriter.cpp @@ -21,8 +21,8 @@ #include "clang/Edit/Commit.h" #include "clang/Edit/EditsReceiver.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" @@ -33,6 +33,7 @@ #include using namespace clang; +using llvm::RewriteBuffer; FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const LangOptions &LangOpts, diff --git a/clang/lib/Frontend/Rewrite/HTMLPrint.cpp b/clang/lib/Frontend/Rewrite/HTMLPrint.cpp index 69baa8f591088c9..5cce193ed1c4f30 100644 --- a/clang/lib/Frontend/Rewrite/HTMLPrint.cpp +++ b/clang/lib/Frontend/Rewrite/HTMLPrint.cpp @@ -20,8 +20,10 @@ #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Frontend/ASTConsumers.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/Support/raw_ostream.h" using namespace clang; +using llvm::RewriteBuffer; //===----------------------------------------------------------------------===// // Functional HTML pretty-printing. diff --git a/clang/lib/Frontend/Rewrite/RewriteMacros.cpp b/clang/lib/Frontend/Rewrite/RewriteMacros.cpp index 5701b271aff103b..b533cabe97f5e9e 100644 --- a/clang/lib/Frontend/Rewrite/RewriteMacros.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteMacros.cpp @@ -11,16 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "clang/Rewrite/Frontend/Rewriters.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Rewrite/Frontend/Rewriters.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace clang; +using llvm::RewriteBuffer; /// isSameToken - Return true if the two specified tokens start have the same /// content. diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 3849e4040b53a17..f618c536b5f3c63 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Rewrite/Frontend/ASTConsumers.h" #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/Attr.h" @@ -23,6 +22,7 @@ #include "clang/Config/config.h" #include "clang/Lex/Lexer.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Rewrite/Frontend/ASTConsumers.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -34,6 +34,7 @@ #if CLANG_ENABLE_OBJC_REWRITER using namespace clang; +using llvm::RewriteBuffer; using llvm::utostr; namespace { diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index bf5176a2b6fb2e3..9db6ddbf0b8908f 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -32,6 +32,7 @@ #if CLANG_ENABLE_OBJC_REWRITER using namespace clang; +using llvm::RewriteBuffer; using llvm::utostr; namespace { diff --git a/clang/lib/Headers/hlsl/hlsl_basic_types.h b/clang/lib/Headers/hlsl/hlsl_basic_types.h index da6903df65ffed7..eff94e0d7f9500e 100644 --- a/clang/lib/Headers/hlsl/hlsl_basic_types.h +++ b/clang/lib/Headers/hlsl/hlsl_basic_types.h @@ -23,52 +23,98 @@ namespace hlsl { // 16-bit integer. typedef unsigned short uint16_t; typedef short int16_t; + +// 16-bit floating point. +typedef half float16_t; #endif +// 32-bit integer. +typedef int int32_t; + // unsigned 32-bit integer. typedef unsigned int uint; +typedef unsigned int uint32_t; + +// 32-bit floating point. +typedef float float32_t; // 64-bit integer. typedef unsigned long uint64_t; typedef long int64_t; +// 64-bit floating point +typedef double float64_t; + // built-in vector data types: #ifdef __HLSL_ENABLE_16_BIT +typedef vector int16_t1; typedef vector int16_t2; typedef vector int16_t3; typedef vector int16_t4; +typedef vector uint16_t1; typedef vector uint16_t2; typedef vector uint16_t3; typedef vector uint16_t4; #endif +typedef vector bool1; typedef vector bool2; typedef vector bool3; typedef vector bool4; +typedef vector int1; typedef vector int2; typedef vector int3; typedef vector int4; +typedef vector uint1; typedef vector uint2; typedef vector uint3; typedef vector uint4; +typedef vector int32_t1; +typedef vector int32_t2; +typedef vector int32_t3; +typedef vector int32_t4; +typedef vector uint32_t1; +typedef vector uint32_t2; +typedef vector uint32_t3; +typedef vector uint32_t4; +typedef vector int64_t1; typedef vector int64_t2; typedef vector int64_t3; typedef vector int64_t4; +typedef vector uint64_t1; typedef vector uint64_t2; typedef vector uint64_t3; typedef vector uint64_t4; +typedef vector half1; typedef vector half2; typedef vector half3; typedef vector half4; - +typedef vector float1; typedef vector float2; typedef vector float3; typedef vector float4; +typedef vector double1; typedef vector double2; typedef vector double3; typedef vector double4; +#ifdef __HLSL_ENABLE_16_BIT +typedef vector float16_t1; +typedef vector float16_t2; +typedef vector float16_t3; +typedef vector float16_t4; +#endif + +typedef vector float32_t1; +typedef vector float32_t2; +typedef vector float32_t3; +typedef vector float32_t4; +typedef vector float64_t1; +typedef vector float64_t2; +typedef vector float64_t3; +typedef vector float64_t4; + } // namespace hlsl #endif //_HLSL_HLSL_BASIC_TYPES_H_ diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index aac89d910bbc839..18c5fe6056b4726 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -425,7 +425,10 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { [[fallthrough]]; default: ParsedAttributes DeclAttrs(AttrFactory); - MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes DeclSpecAttrs(AttrFactory); + while (MaybeParseCXX11Attributes(DeclAttrs) || + MaybeParseGNUAttributes(DeclSpecAttrs)) + ; ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs); continue; } @@ -449,7 +452,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { /// /// export-function-declaration: /// 'export' function-declaration -/// +/// /// export-declaration-group: /// 'export' '{' function-declaration-seq[opt] '}' /// @@ -2004,9 +2007,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); TagUseKind TUK; - if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) == - AllowDefiningTypeSpec::No || - (getLangOpts().OpenMP && OpenMPDirectiveParsing)) + + // C++26 [class.mem.general]p10: If a name-declaration matches the + // syntactic requirements of friend-type-declaration, it is a + // friend-type-declaration. + if (getLangOpts().CPlusPlus && DS.isFriendSpecifiedFirst() && + Tok.isOneOf(tok::comma, tok::ellipsis)) + TUK = TagUseKind::Friend; + else if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) == + AllowDefiningTypeSpec::No || + (getLangOpts().OpenMP && OpenMPDirectiveParsing)) TUK = TagUseKind::Reference; else if (Tok.is(tok::l_brace) || (DSC != DeclSpecContext::DSC_association && @@ -2238,9 +2248,28 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, diag::err_keyword_not_allowed, /*DiagnoseEmptyAttrs=*/true); + // Consume '...' first so we error on the ',' after it if there is one. + SourceLocation EllipsisLoc; + TryConsumeToken(tok::ellipsis, EllipsisLoc); + + // CWG 2917: In a template-declaration whose declaration is a + // friend-type-declaration, the friend-type-specifier-list shall + // consist of exactly one friend-type-specifier. + // + // Essentially, the following is obviously nonsense, so disallow it: + // + // template + // friend class S, int; + // + if (Tok.is(tok::comma)) { + Diag(Tok.getLocation(), + diag::err_friend_template_decl_multiple_specifiers); + SkipUntil(tok::semi, StopBeforeMatch); + } + TagOrTempResult = Actions.ActOnTemplatedFriendTag( getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, - NameLoc, attrs, + NameLoc, EllipsisLoc, attrs, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0)); } else { @@ -2815,6 +2844,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// member-declaration: /// decl-specifier-seq[opt] member-declarator-list[opt] ';' /// function-definition ';'[opt] +/// [C++26] friend-type-declaration /// ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO] /// using-declaration [TODO] /// [C++0x] static_assert-declaration @@ -2847,6 +2877,18 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// constant-initializer: /// '=' constant-expression /// +/// friend-type-declaration: +/// 'friend' friend-type-specifier-list ; +/// +/// friend-type-specifier-list: +/// friend-type-specifier ...[opt] +/// friend-type-specifier-list , friend-type-specifier ...[opt] +/// +/// friend-type-specifier: +/// simple-type-specifier +/// elaborated-type-specifier +/// typename-specifier +/// Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( AccessSpecifier AS, ParsedAttributes &AccessAttrs, ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { @@ -3048,6 +3090,55 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( if (DS.hasTagDefinition()) Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl()); + // Handle C++26's variadic friend declarations. These don't even have + // declarators, so we get them out of the way early here. + if (DS.isFriendSpecifiedFirst() && Tok.isOneOf(tok::comma, tok::ellipsis)) { + Diag(Tok.getLocation(), getLangOpts().CPlusPlus26 + ? diag::warn_cxx23_variadic_friends + : diag::ext_variadic_friends); + + SourceLocation FriendLoc = DS.getFriendSpecLoc(); + SmallVector Decls; + + // Handles a single friend-type-specifier. + auto ParsedFriendDecl = [&](ParsingDeclSpec &DeclSpec) { + SourceLocation VariadicLoc; + TryConsumeToken(tok::ellipsis, VariadicLoc); + + RecordDecl *AnonRecord = nullptr; + Decl *D = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS, DeclSpec, DeclAttrs, TemplateParams, false, + AnonRecord, VariadicLoc); + DeclSpec.complete(D); + if (!D) { + SkipUntil(tok::semi, tok::r_brace); + return true; + } + + Decls.push_back(D); + return false; + }; + + if (ParsedFriendDecl(DS)) + return nullptr; + + while (TryConsumeToken(tok::comma)) { + ParsingDeclSpec DeclSpec(*this, TemplateDiags); + const char *PrevSpec = nullptr; + unsigned DiagId = 0; + DeclSpec.SetFriendSpec(FriendLoc, PrevSpec, DiagId); + ParseDeclarationSpecifiers(DeclSpec, TemplateInfo, AS, + DeclSpecContext::DSC_class, nullptr); + if (ParsedFriendDecl(DeclSpec)) + return nullptr; + } + + ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, + "friend declaration"); + + return Actions.BuildDeclaratorGroup(Decls); + } + ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs, DeclaratorContext::Member); if (TemplateInfo.TemplateParams) diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index b8e15b1aa6ce9e7..1405aef700bec5e 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -21,7 +21,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/Availability.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/LocInfoType.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/Parser.h" diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 6a2088a73c55b91..dad39d8dc736de1 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/ODRDiagsEmitter.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/CharInfo.h" diff --git a/clang/lib/Rewrite/CMakeLists.txt b/clang/lib/Rewrite/CMakeLists.txt index 16550b1b710ef9f..93ecb3c835260fe 100644 --- a/clang/lib/Rewrite/CMakeLists.txt +++ b/clang/lib/Rewrite/CMakeLists.txt @@ -3,9 +3,7 @@ set(LLVM_LINK_COMPONENTS ) add_clang_library(clangRewrite - DeltaTree.cpp HTMLRewrite.cpp - RewriteRope.cpp Rewriter.cpp TokenRewriter.cpp diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index a96ca0764ae73d5..c75835df2c98ee8 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -16,6 +16,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/TokenConcatenation.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/clang/lib/Rewrite/Rewriter.cpp b/clang/lib/Rewrite/Rewriter.cpp index 0e6ae365064463b..68cf797f97905bc 100644 --- a/clang/lib/Rewrite/Rewriter.cpp +++ b/clang/lib/Rewrite/Rewriter.cpp @@ -17,8 +17,8 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" -#include "clang/Rewrite/Core/RewriteRope.h" +#include "llvm/ADT/RewriteBuffer.h" +#include "llvm/ADT/RewriteRope.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -29,113 +29,18 @@ #include using namespace clang; +using llvm::RewriteBuffer; -raw_ostream &RewriteBuffer::write(raw_ostream &os) const { - // Walk RewriteRope chunks efficiently using MoveToNextPiece() instead of the - // character iterator. - for (RopePieceBTreeIterator I = begin(), E = end(); I != E; - I.MoveToNextPiece()) - os << I.piece(); - return os; -} +//===----------------------------------------------------------------------===// +// Rewriter class +//===----------------------------------------------------------------------===// /// Return true if this character is non-new-line whitespace: /// ' ', '\\t', '\\f', '\\v', '\\r'. static inline bool isWhitespaceExceptNL(unsigned char c) { - switch (c) { - case ' ': - case '\t': - case '\f': - case '\v': - case '\r': - return true; - default: - return false; - } + return c == ' ' || c == '\t' || c == '\f' || c == '\v' || c == '\r'; } -void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size, - bool removeLineIfEmpty) { - // Nothing to remove, exit early. - if (Size == 0) return; - - unsigned RealOffset = getMappedOffset(OrigOffset, true); - assert(RealOffset+Size <= Buffer.size() && "Invalid location"); - - // Remove the dead characters. - Buffer.erase(RealOffset, Size); - - // Add a delta so that future changes are offset correctly. - AddReplaceDelta(OrigOffset, -Size); - - if (removeLineIfEmpty) { - // Find the line that the remove occurred and if it is completely empty - // remove the line as well. - - iterator curLineStart = begin(); - unsigned curLineStartOffs = 0; - iterator posI = begin(); - for (unsigned i = 0; i != RealOffset; ++i) { - if (*posI == '\n') { - curLineStart = posI; - ++curLineStart; - curLineStartOffs = i + 1; - } - ++posI; - } - - unsigned lineSize = 0; - posI = curLineStart; - while (posI != end() && isWhitespaceExceptNL(*posI)) { - ++posI; - ++lineSize; - } - if (posI != end() && *posI == '\n') { - Buffer.erase(curLineStartOffs, lineSize + 1/* + '\n'*/); - // FIXME: Here, the offset of the start of the line is supposed to be - // expressed in terms of the original input not the "real" rewrite - // buffer. How do we compute that reliably? It might be tempting to use - // curLineStartOffs + OrigOffset - RealOffset, but that assumes the - // difference between the original and real offset is the same at the - // removed text and at the start of the line, but that's not true if - // edits were previously made earlier on the line. This bug is also - // documented by a FIXME on the definition of - // clang::Rewriter::RewriteOptions::RemoveLineIfEmpty. A reproducer for - // the implementation below is the test RemoveLineIfEmpty in - // clang/unittests/Rewrite/RewriteBufferTest.cpp. - AddReplaceDelta(curLineStartOffs, -(lineSize + 1/* + '\n'*/)); - } - } -} - -void RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str, - bool InsertAfter) { - // Nothing to insert, exit early. - if (Str.empty()) return; - - unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter); - Buffer.insert(RealOffset, Str.begin(), Str.end()); - - // Add a delta so that future changes are offset correctly. - AddInsertDelta(OrigOffset, Str.size()); -} - -/// ReplaceText - This method replaces a range of characters in the input -/// buffer with a new string. This is effectively a combined "remove+insert" -/// operation. -void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength, - StringRef NewStr) { - unsigned RealOffset = getMappedOffset(OrigOffset, true); - Buffer.erase(RealOffset, OrigLength); - Buffer.insert(RealOffset, NewStr.begin(), NewStr.end()); - if (OrigLength != NewStr.size()) - AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength); -} - -//===----------------------------------------------------------------------===// -// Rewriter class -//===----------------------------------------------------------------------===// - /// getRangeSize - Return the size in bytes of the specified range if they /// are in the same file. If not, this returns -1. int Rewriter::getRangeSize(const CharSourceRange &Range, diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 633b8220ffbf11d..29acd06af603be3 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -22,6 +22,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/PartialDiagnostic.h" diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 65b56bd1c8efc73..d0236d08c98e68d 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -433,6 +433,15 @@ static void ProcessAPINotes(Sema &S, VarDecl *D, metadata); } +/// Process API notes for a C field. +static void ProcessAPINotes(Sema &S, FieldDecl *D, + const api_notes::FieldInfo &Info, + VersionedInfoMetadata metadata) { + // Handle common entity information. + ProcessAPINotes(S, D, static_cast(Info), + metadata); +} + /// Process API notes for an Objective-C property. static void ProcessAPINotes(Sema &S, ObjCPropertyDecl *D, const api_notes::ObjCPropertyInfo &Info, @@ -1062,6 +1071,17 @@ void Sema::ProcessAPINotes(Decl *D) { } } + if (auto Field = dyn_cast(D)) { + if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) { + for (auto Reader : APINotes.findAPINotes(D->getLocation())) { + if (auto Context = UnwindTagContext(TagContext, APINotes)) { + auto Info = Reader->lookupField(Context->id, Field->getName()); + ProcessVersionedAPINotes(*this, Field, Info); + } + } + } + } + if (auto Tag = dyn_cast(D)) { for (auto Reader : APINotes.findAPINotes(D->getLocation())) { if (auto Context = UnwindTagContext(TagContext, APINotes)) { diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index d8dd4fe16e3af00..e18872f0dc551e4 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaARM.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Sema.h" diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 641b180527da558..503e93f92571371 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -25,6 +25,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NonTrivialTypeVisitor.h" +#include "clang/AST/MangleNumberingContext.h" #include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" @@ -5000,7 +5001,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, const ParsedAttributesView &DeclAttrs, MultiTemplateParamsArg TemplateParams, bool IsExplicitInstantiation, - RecordDecl *&AnonRecord) { + RecordDecl *&AnonRecord, + SourceLocation EllipsisLoc) { Decl *TagD = nullptr; TagDecl *Tag = nullptr; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -5067,9 +5069,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // whatever routines created it handled the friendship aspect. if (TagD && !Tag) return nullptr; - return ActOnFriendTypeDecl(S, DS, TemplateParams); + return ActOnFriendTypeDecl(S, DS, TemplateParams, EllipsisLoc); } + assert(EllipsisLoc.isInvalid() && + "Friend ellipsis but not friend-specified?"); + // Track whether this decl-specifier declares anything. bool DeclaresAnything = true; @@ -6934,9 +6939,16 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { // by applying it to the function type. if (const auto *A = ATL.getAttrAs()) { const auto *MD = dyn_cast(FD); - if (!MD || MD->isStatic()) { + int NoImplicitObjectError = -1; + if (!MD) + NoImplicitObjectError = 0; + else if (MD->isStatic()) + NoImplicitObjectError = 1; + else if (MD->isExplicitObjectMemberFunction()) + NoImplicitObjectError = 2; + if (NoImplicitObjectError != -1) { S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param) - << !MD << A->getRange(); + << NoImplicitObjectError << A->getRange(); } else if (isa(MD) || isa(MD)) { S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor) << isa(MD) << A->getRange(); @@ -12226,12 +12238,9 @@ void Sema::CheckMain(FunctionDecl *FD, const DeclSpec &DS) { // The main function shall not be declared with a linkage-specification. if (FD->isExternCContext() || (FD->isExternCXXContext() && - FD->getDeclContext()->getRedeclContext()->isTranslationUnit())) { + FD->getDeclContext()->getRedeclContext()->isTranslationUnit())) Diag(FD->getLocation(), diag::ext_main_invalid_linkage_specification) << FD->getLanguageLinkage(); - FD->setInvalidDecl(); - return; - } // C++11 [basic.start.main]p3: // A program that [...] declares main to be inline, static or @@ -18503,11 +18512,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // the program is ill-formed, except when compiling with MSVC extensions // enabled. if (EltTy->isReferenceType()) { - Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? - diag::ext_union_member_of_reference_type : - diag::err_union_member_of_reference_type) - << NewFD->getDeclName() << EltTy; - if (!getLangOpts().MicrosoftExt) + const bool HaveMSExt = + getLangOpts().MicrosoftExt && + !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015); + + Diag(NewFD->getLocation(), + HaveMSExt ? diag::ext_union_member_of_reference_type + : diag::err_union_member_of_reference_type) + << NewFD->getDeclName() << EltTy; + if (!HaveMSExt) NewFD->setInvalidDecl(); } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 3b5e984f4ee7735..73d11ac972b020b 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7123,6 +7123,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, } } +static bool isKernelDecl(Decl *D) { + const FunctionType *FnTy = D->getFunctionType(); + return D->hasAttr() || + (FnTy && FnTy->getCallConv() == CallingConv::CC_AMDGPUKernelCall) || + D->hasAttr() || D->getAttr(); +} + void Sema::ProcessDeclAttributeList( Scope *S, Decl *D, const ParsedAttributesView &AttrList, const ProcessDeclAttributeOptions &Options) { @@ -7163,24 +7170,25 @@ void Sema::ProcessDeclAttributeList( } else if (const auto *A = D->getAttr()) { Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; D->setInvalidDecl(); - } else if (!D->hasAttr()) { - if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; - D->setInvalidDecl(); - } + } + } + if (!isKernelDecl(D)) { + if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; + D->setInvalidDecl(); + } else if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; + D->setInvalidDecl(); + } else if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; + D->setInvalidDecl(); + } else if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << A->isRegularKeywordAttribute() << ExpectedKernelFunction; + D->setInvalidDecl(); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c87edf41f35cee8..d89a47f3e6226a8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7056,11 +7056,16 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { if (!RD->hasConstexprDestructor()) return false; + QualType CanUnqualT = T.getCanonicalType().getUnqualifiedType(); for (const CXXBaseSpecifier &B : RD->bases()) - if (!Check(B.getType(), Check)) + if (B.getType().getCanonicalType().getUnqualifiedType() != + CanUnqualT && + !Check(B.getType(), Check)) return false; for (const FieldDecl *FD : RD->fields()) - if (!Check(FD->getType(), Check)) + if (FD->getType().getCanonicalType().getUnqualifiedType() != + CanUnqualT && + !Check(FD->getType(), Check)) return false; return true; }; @@ -7644,9 +7649,13 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, // parameter is of (possibly different) type β€œreference to C”, // in which case the type of F1 would differ from the type of F2 // in that the type of F1 has an additional parameter; - if (!Context.hasSameType( - ThisType.getNonReferenceType().getUnqualifiedType(), - Context.getRecordType(RD))) { + QualType ExplicitObjectParameter = MD->isExplicitObjectMemberFunction() + ? MD->getParamDecl(0)->getType() + : QualType(); + if (!ExplicitObjectParameter.isNull() && + (!ExplicitObjectParameter->isReferenceType() || + !Context.hasSameType(ExplicitObjectParameter.getNonReferenceType(), + Context.getRecordType(RD)))) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; else { @@ -8730,8 +8739,9 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // If we're out-of-class, this is the class we're comparing. if (!RD) RD = MD->getParent(); - QualType T = MD->getFunctionObjectParameterType(); - if (!T.isConstQualified()) { + QualType T = MD->getFunctionObjectParameterReferenceType(); + if (!T.getNonReferenceType().isConstQualified() && + (MD->isImplicitObjectMemberFunction() || T->isLValueReferenceType())) { SourceLocation Loc, InsertLoc; if (MD->isExplicitObjectMemberFunction()) { Loc = MD->getParamDecl(0)->getBeginLoc(); @@ -8750,11 +8760,17 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, } // Add the 'const' to the type to recover. - const auto *FPT = MD->getType()->castAs(); - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals.addConst(); - MD->setType(Context.getFunctionType(FPT->getReturnType(), - FPT->getParamTypes(), EPI)); + if (MD->isExplicitObjectMemberFunction()) { + assert(T->isLValueReferenceType()); + MD->getParamDecl(0)->setType(Context.getLValueReferenceType( + T.getNonReferenceType().withConst())); + } else { + const auto *FPT = MD->getType()->castAs(); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.TypeQuals.addConst(); + MD->setType(Context.getFunctionType(FPT->getReturnType(), + FPT->getParamTypes(), EPI)); + } } if (MD->isVolatile()) { @@ -8781,18 +8797,15 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, const ParmVarDecl *KnownParm = nullptr; for (const ParmVarDecl *Param : FD->parameters()) { - if (Param->isExplicitObjectParameter()) - continue; QualType ParmTy = Param->getType(); - if (!KnownParm) { auto CTy = ParmTy; // Is it `T const &`? - bool Ok = !IsMethod; + bool Ok = !IsMethod || FD->hasCXXExplicitFunctionObjectParameter(); QualType ExpectedTy; if (RD) ExpectedTy = Context.getRecordType(RD); - if (auto *Ref = CTy->getAs()) { + if (auto *Ref = CTy->getAs()) { CTy = Ref->getPointeeType(); if (RD) ExpectedTy.addConst(); @@ -8800,14 +8813,11 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, } // Is T a class? - if (!Ok) { - } else if (RD) { - if (!RD->isDependentType() && !Context.hasSameType(CTy, ExpectedTy)) - Ok = false; - } else if (auto *CRD = CTy->getAsRecordDecl()) { - RD = cast(CRD); + if (RD) { + Ok &= RD->isDependentType() || Context.hasSameType(CTy, ExpectedTy); } else { - Ok = false; + RD = CTy->getAsCXXRecordDecl(); + Ok &= RD != nullptr; } if (Ok) { @@ -8847,7 +8857,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, assert(FD->getFriendObjectKind() && "expected a friend declaration"); } else { // Out of class, require the defaulted comparison to be a friend (of a - // complete type). + // complete type, per CWG2547). if (RequireCompleteType(FD->getLocation(), Context.getRecordType(RD), diag::err_defaulted_comparison_not_friend, int(DCK), int(1))) @@ -17381,7 +17391,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, DeclResult Sema::ActOnTemplatedFriendTag( Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists) { + SourceLocation EllipsisLoc, const ParsedAttributesView &Attr, + MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); bool IsMemberSpecialization = false; @@ -17425,6 +17436,7 @@ DeclResult Sema::ActOnTemplatedFriendTag( // If it's explicit specializations all the way down, just forget // about the template header and build an appropriate non-templated // friend. TODO: for source fidelity, remember the headers. + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); if (isAllExplicitSpecializations) { if (SS.isEmpty()) { bool Owned = false; @@ -17440,7 +17452,6 @@ DeclResult Sema::ActOnTemplatedFriendTag( /*IsTemplateParamOrArg=*/false, /*OOK=*/OOK_Outside); } - NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, @@ -17462,8 +17473,9 @@ DeclResult Sema::ActOnTemplatedFriendTag( TL.getNamedTypeLoc().castAs().setNameLoc(NameLoc); } - FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, - TSI, FriendLoc, TempParamLists); + FriendDecl *Friend = + FriendDecl::Create(Context, CurContext, NameLoc, TSI, FriendLoc, + EllipsisLoc, TempParamLists); Friend->setAccess(AS_public); CurContext->addDecl(Friend); return Friend; @@ -17471,7 +17483,22 @@ DeclResult Sema::ActOnTemplatedFriendTag( assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); - + // CWG 2917: if it (= the friend-type-specifier) is a pack expansion + // (13.7.4 [temp.variadic]), any packs expanded by that pack expansion + // shall not have been introduced by the template-declaration. + SmallVector Unexpanded; + collectUnexpandedParameterPacks(QualifierLoc, Unexpanded); + unsigned FriendDeclDepth = TempParamLists.front()->getDepth(); + for (UnexpandedParameterPack &U : Unexpanded) { + if (getDepthAndIndex(U).first >= FriendDeclDepth) { + auto *ND = U.first.dyn_cast(); + if (!ND) + ND = U.first.get()->getDecl(); + Diag(U.second, diag::friend_template_decl_malformed_pack_expansion) + << ND->getDeclName() << SourceRange(SS.getBeginLoc(), EllipsisLoc); + return true; + } + } // Handle the case of a templated-scope friend class. e.g. // template class A::B; @@ -17486,8 +17513,9 @@ DeclResult Sema::ActOnTemplatedFriendTag( TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); - FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, - TSI, FriendLoc, TempParamLists); + FriendDecl *Friend = + FriendDecl::Create(Context, CurContext, NameLoc, TSI, FriendLoc, + EllipsisLoc, TempParamLists); Friend->setAccess(AS_public); Friend->setUnsupportedFriend(true); CurContext->addDecl(Friend); @@ -17495,7 +17523,8 @@ DeclResult Sema::ActOnTemplatedFriendTag( } Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, - MultiTemplateParamsArg TempParams) { + MultiTemplateParamsArg TempParams, + SourceLocation EllipsisLoc) { SourceLocation Loc = DS.getBeginLoc(); SourceLocation FriendLoc = DS.getFriendSpecLoc(); @@ -17536,8 +17565,18 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, if (TheDeclarator.isInvalidType()) return nullptr; - if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration)) + // If '...' is present, the type must contain an unexpanded parameter + // pack, and vice versa. + bool Invalid = false; + if (EllipsisLoc.isInvalid() && + DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration)) return nullptr; + if (EllipsisLoc.isValid() && + !TSI->getType()->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << TSI->getTypeLoc().getSourceRange(); + Invalid = true; + } if (!T->isElaboratedTypeSpecifier()) { if (TempParams.size()) { @@ -17583,11 +17622,12 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, Decl *D; if (!TempParams.empty()) + // TODO: Support variadic friend template decls? D = FriendTemplateDecl::Create(Context, CurContext, Loc, TempParams, TSI, FriendLoc); else D = FriendDecl::Create(Context, CurContext, TSI->getTypeLoc().getBeginLoc(), - TSI, FriendLoc); + TSI, FriendLoc, EllipsisLoc); if (!D) return nullptr; @@ -17595,6 +17635,9 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, D->setAccess(AS_public); CurContext->addDecl(D); + if (Invalid) + D->setInvalidDecl(); + return D; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c4aa02ff0c217d2..f495658fe586416 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -25,6 +25,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/MangleNumberingContext.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -6593,6 +6594,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, "should only occur in error-recovery path."); return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides()); + } return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc, ExecConfig, IsExecConfig); } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 2751c7cec2842e3..2f914ddc22a38b8 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/Availability.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtVisitor.h" diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 05d406a8630fbe4..a8461a7f6cf7123 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/MangleNumberingContext.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" diff --git a/clang/lib/Sema/SemaMIPS.cpp b/clang/lib/Sema/SemaMIPS.cpp index 269d927903c5d60..50d210e5b381405 100644 --- a/clang/lib/Sema/SemaMIPS.cpp +++ b/clang/lib/Sema/SemaMIPS.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaMIPS.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Attr.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Sema.h" diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp index 75233689769c5bc..0359d18dd945251 100644 --- a/clang/lib/Sema/SemaObjC.cpp +++ b/clang/lib/Sema/SemaObjC.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/DiagnosticSema.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Attr.h" +#include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 87d81dfaad601b4..74c646f64b42f20 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -21,6 +21,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/OpenMPClause.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/StmtVisitor.h" @@ -1255,16 +1256,8 @@ static const ValueDecl *getCanonicalDecl(const ValueDecl *D) { if (const auto *CED = dyn_cast(D)) if (const auto *ME = dyn_cast(getExprAsWritten(CED->getInit()))) D = ME->getMemberDecl(); - const auto *VD = dyn_cast(D); - const auto *FD = dyn_cast(D); - if (VD != nullptr) { - VD = VD->getCanonicalDecl(); - D = VD; - } else { - assert(FD); - FD = FD->getCanonicalDecl(); - D = FD; - } + + D = cast(D->getCanonicalDecl()); return D; } @@ -3717,6 +3710,7 @@ namespace { class DSAAttrChecker final : public StmtVisitor { DSAStackTy *Stack; Sema &SemaRef; + OpenMPDirectiveKind DKind = OMPD_unknown; bool ErrorFound = false; bool TryCaptureCXXThisMembers = false; CapturedStmt *CS = nullptr; @@ -3748,7 +3742,7 @@ class DSAAttrChecker final : public StmtVisitor { // Try to capture inner this->member references to generate correct mappings // and diagnostics. if (TryCaptureCXXThisMembers || - (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && + (isOpenMPTargetExecutionDirective(DKind) && llvm::any_of(S->getInnermostCapturedStmt()->captures(), [](const CapturedStmt::Capture &C) { return C.capturesThis(); @@ -3818,7 +3812,6 @@ class DSAAttrChecker final : public StmtVisitor { return; SourceLocation ELoc = E->getExprLoc(); - OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); // The default(none) clause requires that each variable that is referenced // in the construct, and does not have a predetermined data-sharing // attribute, must have its data-sharing attribute explicitly determined @@ -3983,7 +3976,6 @@ class DSAAttrChecker final : public StmtVisitor { E->containsUnexpandedParameterPack() || E->isInstantiationDependent()) return; auto *FD = dyn_cast(E->getMemberDecl()); - OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); if (auto *TE = dyn_cast(E->getBase()->IgnoreParenCasts())) { if (!FD) return; @@ -4022,7 +4014,7 @@ class DSAAttrChecker final : public StmtVisitor { OpenMPDefaultmapClauseKind ClauseKind = getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD); OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( - Modifier, /*IsAggregateOrDeclareTarget*/ true); + Modifier, /*IsAggregateOrDeclareTarget=*/true); ImplicitMap[ClauseKind][Kind].emplace_back(E); return; } @@ -4065,8 +4057,7 @@ class DSAAttrChecker final : public StmtVisitor { if (isOpenMPTargetExecutionDirective(DKind)) { OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map, - Stack->getCurrentDirective(), - /*NoDiagnose=*/true)) + DKind, /*NoDiagnose=*/true)) return; const auto *VD = cast( CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl()); @@ -4119,8 +4110,7 @@ class DSAAttrChecker final : public StmtVisitor { // Skip analysis of arguments of implicitly defined map clause for target // directives. if (C && !((isa(C) || isa(C)) && - C->isImplicit() && - !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) { + C->isImplicit() && !isOpenMPTaskingDirective(DKind))) { for (Stmt *CC : C->children()) { if (CC) Visit(CC); @@ -4169,7 +4159,7 @@ class DSAAttrChecker final : public StmtVisitor { VarDecl *VD = Cap.getCapturedVar(); // Do not try to map the variable if it or its sub-component was mapped // already. - if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && + if (isOpenMPTargetExecutionDirective(DKind) && Stack->checkMappableExprComponentListsForDecl( VD, /*CurrentRegionOnly=*/true, [](OMPClauseMappableExprCommon::MappableExprComponentListRef, @@ -4200,8 +4190,9 @@ class DSAAttrChecker final : public StmtVisitor { DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS) : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) { + DKind = S->getCurrentDirective(); // Process declare target link variables for the target directives. - if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) { + if (isOpenMPTargetExecutionDirective(DKind)) { for (DeclRefExpr *E : Stack->getLinkGlobals()) Visit(E); } @@ -4588,7 +4579,7 @@ static bool checkOrderedOrderSpecified(Sema &S, StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S, ArrayRef Clauses) { handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(), - /* ScopeEntry */ false); + /*ScopeEntry=*/false); if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective())) return S; @@ -7059,8 +7050,8 @@ void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( QualType UDeclTy = UDecl->getType(); if (!UDeclTy->isDependentType()) { QualType NewType = getASTContext().mergeFunctionTypes( - FType, UDeclTy, /* OfBlockPointer */ false, - /* Unqualified */ false, /* AllowCXX */ true); + FType, UDeclTy, /*OfBlockPointer=*/false, + /*Unqualified=*/false, /*AllowCXX=*/true); if (NewType.isNull()) continue; } @@ -7106,9 +7097,8 @@ void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( FD = cast(D); auto *VariantFuncRef = DeclRefExpr::Create( getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), FD, - /* RefersToEnclosingVariableOrCapture */ false, - /* NameLoc */ FD->getLocation(), FD->getType(), - ExprValueKind::VK_PRValue); + /*RefersToEnclosingVariableOrCapture=*/false, + /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue); OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit( @@ -7170,7 +7160,7 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, OMPTraitInfo &TI = A->getTraitInfo(); TI.getAsVariantMatchInfo(Context, VMI); if (!isVariantApplicableInContext(VMI, OMPCtx, - /* DeviceSetOnly */ false)) + /*DeviceSetOnly=*/false)) continue; VMIs.push_back(VMI); @@ -7206,7 +7196,7 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, auto *MemberCall = dyn_cast(CE); BestExpr = MemberExpr::CreateImplicit( Context, MemberCall->getImplicitObjectArgument(), - /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy, + /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy, MemberCall->getValueKind(), MemberCall->getObjectKind()); } NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, @@ -7216,8 +7206,8 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee(); QualType NewType = getASTContext().mergeFunctionTypes( CalleeFnType, NewCalleeFnDecl->getType(), - /* OfBlockPointer */ false, - /* Unqualified */ false, /* AllowCXX */ true); + /*OfBlockPointer=*/false, + /*Unqualified=*/false, /*AllowCXX=*/true); if (!NewType.isNull()) break; // Don't use the call if the function type was not compatible. @@ -7698,6 +7688,52 @@ struct LoopIterationSpace final { Expr *FinalCondition = nullptr; }; +/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls +/// set are referenced. Used for verifying loop nest structure before +/// performing a loop collapse operation. +class ForSubExprChecker final : public RecursiveASTVisitor { + const llvm::SmallPtrSetImpl &CollapsedLoopVarDecls; + VarDecl *ForbiddenVar = nullptr; + SourceRange ErrLoc; + +public: + explicit ForSubExprChecker( + const llvm::SmallPtrSetImpl &CollapsedLoopVarDecls) + : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {} + + // We want to visit implicit code, i.e. synthetic initialisation statements + // created during range-for lowering. + bool shouldVisitImplicitCode() const { return true; } + + bool VisitDeclRefExpr(DeclRefExpr *E) { + ValueDecl *VD = E->getDecl(); + if (!isa(VD)) + return true; + VarDecl *V = VD->getPotentiallyDecomposedVarDecl(); + if (V->getType()->isReferenceType()) { + VarDecl *VD = V->getDefinition(); + if (VD->hasInit()) { + Expr *I = VD->getInit(); + DeclRefExpr *DRE = dyn_cast(I); + if (!DRE) + return true; + V = DRE->getDecl()->getPotentiallyDecomposedVarDecl(); + } + } + Decl *Canon = V->getCanonicalDecl(); + if (CollapsedLoopVarDecls.contains(Canon)) { + ForbiddenVar = V; + ErrLoc = E->getSourceRange(); + return false; + } + + return true; + } + + VarDecl *getForbiddenVar() const { return ForbiddenVar; } + SourceRange getErrRange() const { return ErrLoc; } +}; + /// Helper class for checking canonical form of the OpenMP loops and /// extracting iteration space of each loop in the loop nest, that will be used /// for IR generation. @@ -7712,6 +7748,8 @@ class OpenMPIterationSpaceChecker { SourceLocation DefaultLoc; /// A location for diagnostics (when increment is not compatible). SourceLocation ConditionLoc; + /// The set of variables declared within the (to be collapsed) loop nest. + const llvm::SmallPtrSetImpl &CollapsedLoopVarDecls; /// A source location for referring to loop init later. SourceRange InitSrcRange; /// A source location for referring to condition later. @@ -7755,10 +7793,13 @@ class OpenMPIterationSpaceChecker { Expr *Condition = nullptr; public: - OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular, - DSAStackTy &Stack, SourceLocation DefaultLoc) + OpenMPIterationSpaceChecker( + Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack, + SourceLocation DefaultLoc, + const llvm::SmallPtrSetImpl &CollapsedLoopDecls) : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular), - Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {} + Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc), + CollapsedLoopVarDecls(CollapsedLoopDecls) {} /// Check init-expr for canonical loop form and save loop counter /// variable - #Var and its initialization value - #LB. bool checkAndSetInit(Stmt *S, bool EmitDiags = true); @@ -8079,6 +8120,16 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { if (!ExprTemp->cleanupsHaveSideEffects()) S = ExprTemp->getSubExpr(); + if (!CollapsedLoopVarDecls.empty()) { + ForSubExprChecker FSEC{CollapsedLoopVarDecls}; + if (!FSEC.TraverseStmt(S)) { + SourceRange Range = FSEC.getErrRange(); + SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var) + << Range.getEnd() << 0 << FSEC.getForbiddenVar(); + return true; + } + } + InitSrcRange = S->getSourceRange(); if (Expr *E = dyn_cast(S)) S = E->IgnoreParens(); @@ -8182,6 +8233,17 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { } Condition = S; S = getExprAsWritten(S); + + if (!CollapsedLoopVarDecls.empty()) { + ForSubExprChecker FSEC{CollapsedLoopVarDecls}; + if (!FSEC.TraverseStmt(S)) { + SourceRange Range = FSEC.getErrRange(); + SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var) + << Range.getEnd() << 1 << FSEC.getForbiddenVar(); + return true; + } + } + SourceLocation CondLoc = S->getBeginLoc(); auto &&CheckAndSetCond = [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS, @@ -8280,6 +8342,16 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { if (!ExprTemp->cleanupsHaveSideEffects()) S = ExprTemp->getSubExpr(); + if (!CollapsedLoopVarDecls.empty()) { + ForSubExprChecker FSEC{CollapsedLoopVarDecls}; + if (!FSEC.TraverseStmt(S)) { + SourceRange Range = FSEC.getErrRange(); + SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var) + << Range.getEnd() << 2 << FSEC.getForbiddenVar(); + return true; + } + } + IncrementSrcRange = S->getSourceRange(); S = S->IgnoreParens(); if (auto *UO = dyn_cast(S)) { @@ -9001,8 +9073,9 @@ void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, return; DSAStack->loopStart(); + llvm::SmallPtrSet EmptyDeclSet; OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true, - *DSAStack, ForLoc); + *DSAStack, ForLoc, EmptyDeclSet); if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) { if (ValueDecl *D = ISC.getLoopDecl()) { auto *VD = dyn_cast(D); @@ -9099,7 +9172,8 @@ static bool checkOpenMPIterationSpace( Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef ResultIterSpaces, - llvm::MapVector &Captures) { + llvm::MapVector &Captures, + const llvm::SmallPtrSetImpl &CollapsedLoopVarDecls) { bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind); // OpenMP [2.9.1, Canonical Loop Form] // for (init-expr; test-expr; incr-expr) structured-block @@ -9138,7 +9212,8 @@ static bool checkOpenMPIterationSpace( return false; OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA, - For ? For->getForLoc() : CXXFor->getForLoc()); + For ? For->getForLoc() : CXXFor->getForLoc(), + CollapsedLoopVarDecls); // Check init. Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt(); @@ -9415,7 +9490,7 @@ static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { if (HasBits >= Bits) return ExprResult(E); // OK to convert to signed, because new type has more bits than old. - QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true); + QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true); return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting, true); } @@ -9505,6 +9580,39 @@ static Expr *buildPostUpdate(Sema &S, ArrayRef PostUpdates) { return PostUpdate; } +/// Look for variables declared in the body parts of a for-loop nest. Used +/// for verifying loop nest structure before performing a loop collapse +/// operation. +class ForVarDeclFinder final : public RecursiveASTVisitor { + int NestingDepth = 0; + llvm::SmallPtrSetImpl &VarDecls; + +public: + explicit ForVarDeclFinder(llvm::SmallPtrSetImpl &VD) + : VarDecls(VD) {} + + bool VisitForStmt(ForStmt *F) { + ++NestingDepth; + TraverseStmt(F->getBody()); + --NestingDepth; + return false; + } + + bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) { + ++NestingDepth; + TraverseStmt(RF->getBody()); + --NestingDepth; + return false; + } + + bool VisitVarDecl(VarDecl *D) { + Decl *C = D->getCanonicalDecl(); + if (NestingDepth > 0) + VarDecls.insert(C); + return true; + } +}; + /// Called on a for stmt to check itself and nested loops (if any). /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, /// number of collapsed loops otherwise. @@ -9517,6 +9625,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, unsigned NestedLoopCount = 1; bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) && !isOpenMPLoopTransformationDirective(DKind); + llvm::SmallPtrSet CollapsedLoopVarDecls; if (CollapseLoopCountExpr) { // Found 'collapse' clause - calculate collapse number. @@ -9524,6 +9633,9 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (!CollapseLoopCountExpr->isValueDependent() && CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { NestedLoopCount = Result.Val.getInt().getLimitedValue(); + + ForVarDeclFinder FVDF{CollapsedLoopVarDecls}; + FVDF.TraverseStmt(AStmt); } else { Built.clear(/*Size=*/1); return 1; @@ -9561,11 +9673,13 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, SupportsNonPerfectlyNested, NumLoops, [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount, CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA, - &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) { + &IterSpaces, &Captures, + &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) { if (checkOpenMPIterationSpace( DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr, - VarsWithImplicitDSA, IterSpaces, Captures)) + VarsWithImplicitDSA, IterSpaces, Captures, + CollapsedLoopVarDecls)) return true; if (Cnt > 0 && Cnt >= NestedLoopCount && IterSpaces[Cnt].CounterVar) { @@ -9600,7 +9714,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, })) return 0; - Built.clear(/* size */ NestedLoopCount); + Built.clear(/*size=*/NestedLoopCount); if (SemaRef.CurContext->isDependentContext()) return NestedLoopCount; @@ -9754,13 +9868,13 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl(LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), - /*DirectInit*/ false); + /*DirectInit=*/false); // Upper bound variable, initialized with last iteration number. VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(), - /*DirectInit*/ false); + /*DirectInit=*/false); // A 32-bit variable-flag where runtime returns 1 for the last iteration. // This will be used to implement clause 'lastprivate'. @@ -9769,7 +9883,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc); SemaRef.AddInitializerToDecl(ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), - /*DirectInit*/ false); + /*DirectInit=*/false); // Stride variable returned by runtime (we initialize it to 1 by default). VarDecl *STDecl = @@ -9777,7 +9891,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc); SemaRef.AddInitializerToDecl(STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), - /*DirectInit*/ false); + /*DirectInit=*/false); // Build expression: UB = min(UB, LastIteration) // It is necessary for CodeGen of directives with static scheduling. @@ -9788,7 +9902,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); - EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); + EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false); // If we have a combined directive that combines 'distribute', 'for' or // 'simd' we need to be able to access the bounds of the schedule of the @@ -9801,14 +9915,14 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl( CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), - /*DirectInit*/ false); + /*DirectInit=*/false); // Upper bound variable, initialized with last iteration number. VarDecl *CombUBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub"); CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(), - /*DirectInit*/ false); + /*DirectInit=*/false); ExprResult CombIsUBGreater = SemaRef.BuildBinOp( CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get()); @@ -9818,7 +9932,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombCondOp.get()); CombEUB = - SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false); const CapturedDecl *CD = cast(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' @@ -9854,7 +9968,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); - Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false); if (isOpenMPLoopBoundSharingDirective(DKind)) { Expr *CombRHS = @@ -9867,7 +9981,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, CombInit = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); CombInit = - SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false); } } @@ -9887,7 +10001,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) .get(); BoundUB = - SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get(); + SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get(); } ExprResult Cond = (isOpenMPWorksharingDirective(DKind) || @@ -9916,7 +10030,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) .get(); BoundCombUB = - SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false) + SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false) .get(); } CombCond = @@ -9931,7 +10045,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (!Inc.isUsable()) return 0; Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); - Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); + Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false); if (!Inc.isUsable()) return 0; @@ -9952,7 +10066,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); NextLB = - SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false); if (!NextLB.isUsable()) return 0; // UB + ST @@ -9963,7 +10077,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); NextUB = - SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false); if (!NextUB.isUsable()) return 0; if (isOpenMPLoopBoundSharingDirective(DKind)) { @@ -9975,7 +10089,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB.get()); CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (!CombNextLB.isUsable()) return 0; // UB + ST @@ -9987,7 +10101,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB.get()); CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (!CombNextUB.isUsable()) return 0; } @@ -10010,7 +10124,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc.get()); DistInc = - SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false); assert(DistInc.isUsable() && "distribute inc expr was not built"); // Build expression: UB = min(UB, prevUB) for #for in composite or combined @@ -10033,7 +10147,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), CondOp.get()); PrevEUB = - SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false); // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in // parallel for is in combination with a distribute directive with @@ -10047,7 +10161,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) .get(); BoundPrevUB = - SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false) + SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false) .get(); } ParForInDistCond = @@ -15319,7 +15433,7 @@ SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc, class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser { public: IntConvertDiagnoser() - : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {} + : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {} SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) override { return S.Diag(Loc, diag::err_omp_not_integral) << T; @@ -15542,7 +15656,7 @@ static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, } Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy, Sema::AA_Initializing, - /* AllowExplicit */ true); + /*AllowExplicit=*/true); if (!Res.isUsable()) { ErrorFound = true; break; @@ -17645,7 +17759,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause( if (AssignmentOp.isInvalid()) continue; AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc, - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (AssignmentOp.isInvalid()) continue; @@ -18362,7 +18476,7 @@ static bool actOnOMPReductionKindClause( // A list item that appears in a reduction clause must not be // const-qualified. if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc, - /*AcceptIfMutable*/ false, ASE || OASE)) + /*AcceptIfMutable=*/false, ASE || OASE)) continue; OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); @@ -18755,7 +18869,7 @@ static bool actOnOMPReductionKindClause( } if (ReductionOp.isUsable()) ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (!ReductionOp.isUsable()) continue; } @@ -19174,7 +19288,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPLinearClause( ExprResult CalcStep = SemaRef.BuildBinOp( SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr); CalcStep = - SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); + SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -19263,7 +19377,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Update = *CurPrivate; Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); // Build final: Var = PrivCopy; ExprResult Final; @@ -19274,7 +19388,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Final = *CurPrivate; Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); @@ -19453,7 +19567,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef VarList, continue; AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (AssignmentOp.isInvalid()) continue; @@ -19562,7 +19676,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef VarList, if (AssignmentOp.isInvalid()) continue; AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc, - /*DiscardedValue*/ false); + /*DiscardedValue=*/false); if (AssignmentOp.isInvalid()) continue; @@ -20948,7 +21062,7 @@ static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, BaseType, MapperId, Maps, nullptr); Scope *Scope = S.getScopeForContext(DCT); if (Scope) - S.PushOnScopeChains(DMD, Scope, /*AddToContext*/ false); + S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false); DCT->addDecl(DMD); DMD->setAccess(clang::AS_none); auto *VD = cast(MapperVarRef)->getDecl(); diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp index e0a978e6cf5b97c..b6802d6890ed177 100644 --- a/clang/lib/Sema/SemaPPC.cpp +++ b/clang/lib/Sema/SemaPPC.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/APSInt.h" diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 2b55c598d55c038..f2d13d456c25fc6 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -10,6 +10,7 @@ #include "clang/Sema/SemaSYCL.h" #include "clang/AST/Mangle.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Sema/Attr.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Sema.h" diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index d283eaa511011b3..ba681671eb3290f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -281,7 +281,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { E = WarnExpr; if (const auto *Cast = dyn_cast(E)) if (Cast->getCastKind() == CK_NoOp || - Cast->getCastKind() == CK_ConstructorConversion) + Cast->getCastKind() == CK_ConstructorConversion || + Cast->getCastKind() == CK_IntegralCast) E = Cast->getSubExpr()->IgnoreImpCasts(); if (const CallExpr *CE = dyn_cast(E)) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 25585f683752ac4..0afe6064bab185e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10124,8 +10124,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // instantiated from the member definition associated with its class // template. UnresolvedSet<8> TemplateMatches; - FunctionDecl *NonTemplateMatch = nullptr; - TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); + OverloadCandidateSet NonTemplateMatches(D.getBeginLoc(), + OverloadCandidateSet::CSK_Normal); + TemplateSpecCandidateSet FailedTemplateCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { NamedDecl *Prev = *P; @@ -10137,9 +10138,18 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (Method->getPrimaryTemplate()) { TemplateMatches.addDecl(Method, P.getAccess()); } else { - // FIXME: Can this assert ever happen? Needs a test. - assert(!NonTemplateMatch && "Multiple NonTemplateMatches"); - NonTemplateMatch = Method; + OverloadCandidate &C = NonTemplateMatches.addCandidate(); + C.FoundDecl = P.getPair(); + C.Function = Method; + C.Viable = true; + ConstraintSatisfaction S; + if (Method->getTrailingRequiresClause() && + (CheckFunctionConstraints(Method, S, D.getIdentifierLoc(), + /*ForOverloadResolution=*/true) || + !S.IsSatisfied)) { + C.Viable = false; + C.FailureKind = ovl_fail_constraints_not_satisfied; + } } } } @@ -10149,16 +10159,16 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!FunTmpl) continue; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(FailedTemplateCandidates.getLocation()); FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult TDK = DeduceTemplateArguments( FunTmpl, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), R, Specialization, Info); TDK != TemplateDeductionResult::Success) { // Keep track of almost-matches. - FailedCandidates.addCandidate() - .set(P.getPair(), FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK, Info)); + FailedTemplateCandidates.addCandidate().set( + P.getPair(), FunTmpl->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, TDK, Info)); (void)TDK; continue; } @@ -10172,7 +10182,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, CUDA().IdentifyTarget(Specialization, /* IgnoreImplicitHDAttr = */ true) != CUDA().IdentifyTarget(D.getDeclSpec().getAttributes())) { - FailedCandidates.addCandidate().set( + FailedTemplateCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo( Context, TemplateDeductionResult::CUDATargetMismatch, Info)); @@ -10182,12 +10192,40 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateMatches.addDecl(Specialization, P.getAccess()); } - FunctionDecl *Specialization = NonTemplateMatch; + FunctionDecl *Specialization = nullptr; + if (!NonTemplateMatches.empty()) { + unsigned Msg = 0; + OverloadCandidateDisplayKind DisplayKind; + OverloadCandidateSet::iterator Best; + switch (NonTemplateMatches.BestViableFunction(*this, D.getIdentifierLoc(), + Best)) { + case OR_Success: + case OR_Deleted: + Specialization = cast(Best->Function); + break; + case OR_Ambiguous: + Msg = diag::err_explicit_instantiation_ambiguous; + DisplayKind = OCD_AmbiguousCandidates; + break; + case OR_No_Viable_Function: + Msg = diag::err_explicit_instantiation_no_candidate; + DisplayKind = OCD_AllCandidates; + break; + } + if (Msg) { + PartialDiagnostic Diag = PDiag(Msg) << Name; + NonTemplateMatches.NoteCandidates( + PartialDiagnosticAt(D.getIdentifierLoc(), Diag), *this, DisplayKind, + {}); + return true; + } + } + if (!Specialization) { // Find the most specialized function template specialization. UnresolvedSetIterator Result = getMostSpecialized( - TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates, - D.getIdentifierLoc(), + TemplateMatches.begin(), TemplateMatches.end(), + FailedTemplateCandidates, D.getIdentifierLoc(), PDiag(diag::err_explicit_instantiation_not_known) << Name, PDiag(diag::err_explicit_instantiation_ambiguous) << Name, PDiag(diag::note_explicit_instantiation_candidate)); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index ec951d5ac06dbc6..35bc8cd713f06c6 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -28,6 +28,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/ExceptionSpecificationType.h" @@ -4462,6 +4463,9 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( ParamTypesForArgChecking.push_back(ParamType); if (ParamIdx == 0 && HasExplicitObject) { + if (ObjectType.isNull()) + return TemplateDeductionResult::InvalidExplicitArguments; + if (auto Result = DeduceCallArgument(ParamType, 0, /*ExplicitObjectArgument=*/true); Result != TemplateDeductionResult::Success) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f93cd113988ae42..a58854acb21fa5b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyDeclStackTrace.h" +#include "clang/AST/TypeOrdering.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -1442,8 +1443,47 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { if (D->isUnsupportedFriend()) { InstTy = Ty; } else { - InstTy = SemaRef.SubstType(Ty, TemplateArgs, - D->getLocation(), DeclarationName()); + if (D->isPackExpansion()) { + SmallVector Unexpanded; + SemaRef.collectUnexpandedParameterPacks(Ty->getTypeLoc(), Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without packs"); + + bool ShouldExpand = true; + bool RetainExpansion = false; + std::optional NumExpansions; + if (SemaRef.CheckParameterPacksForExpansion( + D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, + TemplateArgs, ShouldExpand, RetainExpansion, NumExpansions)) + return nullptr; + + assert(!RetainExpansion && + "should never retain an expansion for a variadic friend decl"); + + if (ShouldExpand) { + SmallVector Decls; + for (unsigned I = 0; I != *NumExpansions; I++) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + TypeSourceInfo *TSI = SemaRef.SubstType( + Ty, TemplateArgs, D->getEllipsisLoc(), DeclarationName()); + if (!TSI) + return nullptr; + + auto FD = + FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), + TSI, D->getFriendLoc()); + + FD->setAccess(AS_public); + Owner->addDecl(FD); + Decls.push_back(FD); + } + + // Just drop this node; we have no use for it anymore. + return nullptr; + } + } + + InstTy = SemaRef.SubstType(Ty, TemplateArgs, D->getLocation(), + DeclarationName()); } if (!InstTy) return nullptr; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 08020f9f889270a..4b1bb05464f7dca 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -20,6 +20,8 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/LocInfoType.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" diff --git a/clang/lib/Sema/SemaX86.cpp b/clang/lib/Sema/SemaX86.cpp index a0756f167deae61..45c4a1c80b40835 100644 --- a/clang/lib/Sema/SemaX86.cpp +++ b/clang/lib/Sema/SemaX86.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaX86.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Attr.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Sema.h" diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a9199f7e50f5dc8..ef160228933c598 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2361,6 +2361,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { D->NextFriend = readDeclID().getRawValue(); D->UnsupportedFriend = (Record.readInt() != 0); D->FriendLoc = readSourceLocation(); + D->EllipsisLoc = readSourceLocation(); } void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8ae07907a04abaa..a33f2a41a654974 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1128,7 +1128,6 @@ void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { (BinaryOperator::Opcode)CurrentUnpackingBits->getNextBits(/*Width=*/6)); bool hasFP_Features = CurrentUnpackingBits->getNextBit(); E->setHasStoredFPFeatures(hasFP_Features); - E->setExcludedOverflowPattern(CurrentUnpackingBits->getNextBit()); E->setLHS(Record.readSubExpr()); E->setRHS(Record.readSubExpr()); E->setOperatorLoc(readSourceLocation()); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 8a4ca54349e38f1..555f6325da646bf 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1660,6 +1660,7 @@ void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) { Record.AddDeclRef(D->getNextFriend()); Record.push_back(D->UnsupportedFriend); Record.AddSourceLocation(D->FriendLoc); + Record.AddSourceLocation(D->EllipsisLoc); Code = serialization::DECL_FRIEND; } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index c292d0a789c7cd9..038616a675b7271 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1063,7 +1063,6 @@ void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) { CurrentPackingBits.addBits(E->getOpcode(), /*Width=*/6); bool HasFPFeatures = E->hasStoredFPFeatures(); CurrentPackingBits.addBit(HasFPFeatures); - CurrentPackingBits.addBit(E->hasExcludedOverflowPattern()); Record.AddStmt(E->getLHS()); Record.AddStmt(E->getRHS()); Record.AddSourceLocation(E->getOperatorLoc()); diff --git a/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp index 8f1c31763e212c3..f50b5cd3c9e497e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp @@ -48,7 +48,7 @@ bool StringChecker::isCharToStringCtor(const CallEvent &Call, // Verify that the parameters have the expected types: // - arg 1: `const CharT *` - // - arg 2: some allocator - which is definately not `size_t`. + // - arg 2: some allocator - which is definitely not `size_t`. const QualType Arg1Ty = Call.getArgExpr(0)->getType().getCanonicalType(); const QualType Arg2Ty = Call.getArgExpr(1)->getType().getCanonicalType(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 686310d38ebd58f..493914f88ba9a50 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3807,6 +3807,14 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); } + // Do not reason about locations passed inside inline assembly. + for (const Expr *I : A->inputs()) { + SVal X = state->getSVal(I, Pred->getLocationContext()); + + if (std::optional LV = X.getAs()) + state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); + } + Bldr.generateNode(A, Pred, state); } diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index fb5030d373c2f18..28d9de2973b01fa 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -27,6 +27,7 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallString.h" @@ -52,6 +53,7 @@ using namespace clang; using namespace ento; +using llvm::RewriteBuffer; //===----------------------------------------------------------------------===// // Boilerplate. diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp index 269f17a6db4cfc1..9acf00263b5a8ce 100644 --- a/clang/lib/Tooling/Core/Replacement.cpp +++ b/clang/lib/Tooling/Core/Replacement.cpp @@ -19,9 +19,9 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" #include "clang/Rewrite/Core/Rewriter.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" diff --git a/clang/test/APINotes/Inputs/Headers/Fields.apinotes b/clang/test/APINotes/Inputs/Headers/Fields.apinotes new file mode 100644 index 000000000000000..931da52ba29d183 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Fields.apinotes @@ -0,0 +1,23 @@ +--- +Name: Fields +Tags: +- Name: IntWrapper + Fields: + - Name: value + Availability: none + AvailabilityMsg: "oh no" +- Name: Outer + Tags: + - Name: Inner + Fields: + - Name: value + Availability: none + AvailabilityMsg: "oh no 2" + Methods: + - Name: value + Availability: none + AvailabilityMsg: "this should have no effect" +Functions: +- Name: value + Availability: none + AvailabilityMsg: "this should have no effect" diff --git a/clang/test/APINotes/Inputs/Headers/Fields.h b/clang/test/APINotes/Inputs/Headers/Fields.h new file mode 100644 index 000000000000000..dbd342da4778922 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Fields.h @@ -0,0 +1,21 @@ +struct IntWrapper { + int value; + + bool : 1; + + enum { + one, + two, + three + }; + union { + int a; + char b; + }; +}; + +struct Outer { + struct Inner { + int value; + }; +}; diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index faf6042c78d576e..7d304863398ecfc 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -12,6 +12,11 @@ module ExportAs { export * } +module Fields { + header "Fields.h" + export * +} + module HeaderLib { header "HeaderLib.h" } diff --git a/clang/test/APINotes/fields.cpp b/clang/test/APINotes/fields.cpp new file mode 100644 index 000000000000000..8dea2229b4e0a27 --- /dev/null +++ b/clang/test/APINotes/fields.cpp @@ -0,0 +1,17 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Fields -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Fields -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter IntWrapper::value -x c++ | FileCheck --check-prefix=CHECK-FIELD %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Fields -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Outer::Inner::value -x c++ | FileCheck --check-prefix=CHECK-DEEP-FIELD %s + +#include "Fields.h" + +// CHECK-FIELD: Dumping IntWrapper::value: +// CHECK-FIELD-NEXT: FieldDecl {{.+}} value +// CHECK-FIELD: UnavailableAttr {{.+}} <> "oh no" + +// CHECK-DEEP-FIELD: Dumping Outer::Inner::value: +// CHECK-DEEP-FIELD-NEXT: FieldDecl {{.+}} value +// CHECK-DEEP-FIELD: UnavailableAttr {{.+}} <> "oh no 2" + +// CHECK-FIELD-NOT: this should have no effect +// CHECK-DEEP-FIELD-NOT: this should have no effect diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp similarity index 100% rename from clang/test/AST/Interp/arrays.cpp rename to clang/test/AST/ByteCode/arrays.cpp diff --git a/clang/test/AST/Interp/atomic.c b/clang/test/AST/ByteCode/atomic.c similarity index 100% rename from clang/test/AST/Interp/atomic.c rename to clang/test/AST/ByteCode/atomic.c diff --git a/clang/test/AST/Interp/atomic.cpp b/clang/test/AST/ByteCode/atomic.cpp similarity index 100% rename from clang/test/AST/Interp/atomic.cpp rename to clang/test/AST/ByteCode/atomic.cpp diff --git a/clang/test/AST/Interp/bitfields.cpp b/clang/test/AST/ByteCode/bitfields.cpp similarity index 100% rename from clang/test/AST/Interp/bitfields.cpp rename to clang/test/AST/ByteCode/bitfields.cpp diff --git a/clang/test/AST/Interp/builtin-align-cxx.cpp b/clang/test/AST/ByteCode/builtin-align-cxx.cpp similarity index 100% rename from clang/test/AST/Interp/builtin-align-cxx.cpp rename to clang/test/AST/ByteCode/builtin-align-cxx.cpp diff --git a/clang/test/AST/Interp/builtin-constant-p.cpp b/clang/test/AST/ByteCode/builtin-constant-p.cpp similarity index 100% rename from clang/test/AST/Interp/builtin-constant-p.cpp rename to clang/test/AST/ByteCode/builtin-constant-p.cpp diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp similarity index 100% rename from clang/test/AST/Interp/builtin-functions.cpp rename to clang/test/AST/ByteCode/builtin-functions.cpp diff --git a/clang/test/AST/Interp/builtins.cpp b/clang/test/AST/ByteCode/builtins.cpp similarity index 100% rename from clang/test/AST/Interp/builtins.cpp rename to clang/test/AST/ByteCode/builtins.cpp diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/ByteCode/c.c similarity index 99% rename from clang/test/AST/Interp/c.c rename to clang/test/AST/ByteCode/c.c index 13a5e082a125f20..b38259d41130eb1 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/ByteCode/c.c @@ -295,4 +295,5 @@ void T1(void) { // pedantic-warning {{use of GNU statement expression extension}} } - +enum teste1 test1f(void), (*test1)(void) = test1f; // pedantic-warning {{ISO C forbids forward references to 'enum' types}} +enum teste1 { TEST1 }; diff --git a/clang/test/AST/Interp/c23.c b/clang/test/AST/ByteCode/c23.c similarity index 100% rename from clang/test/AST/Interp/c23.c rename to clang/test/AST/ByteCode/c23.c diff --git a/clang/test/AST/ByteCode/codegen.c b/clang/test/AST/ByteCode/codegen.c new file mode 100644 index 000000000000000..8434992823010e7 --- /dev/null +++ b/clang/test/AST/ByteCode/codegen.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s + +typedef __INTPTR_TYPE__ intptr_t; + +const intptr_t Z1 = (intptr_t)(((char*)-1LL) + 1); +// CHECK: @Z1 = constant i64 0 + +const intptr_t Z2 = (intptr_t)(((char*)1LL) - 1); +// CHECK: @Z2 = constant i64 0 + +struct A { + char num_fields; +}; +struct B { + char a, b[1]; +}; +const int A = (char *)(&( (struct B *)(16) )->b[0]) - (char *)(16); +// CHECK: @A = constant i32 1 diff --git a/clang/test/AST/Interp/codegen.cpp b/clang/test/AST/ByteCode/codegen.cpp similarity index 91% rename from clang/test/AST/Interp/codegen.cpp rename to clang/test/AST/ByteCode/codegen.cpp index 920a5ad7ba3e8fc..9fac28a52d3150d 100644 --- a/clang/test/AST/Interp/codegen.cpp +++ b/clang/test/AST/ByteCode/codegen.cpp @@ -64,3 +64,12 @@ namespace Bitfield { // CHECK: store ptr @_ZGRN8Bitfield1rE_, ptr @_ZN8Bitfield1rE, align 8 int &&r = S().a; } + +namespace Null { + decltype(nullptr) null(); + // CHECK: call {{.*}} @_ZN4Null4nullEv( + int *p = null(); + struct S {}; + // CHECK: call {{.*}} @_ZN4Null4nullEv( + int S::*q = null(); +} diff --git a/clang/test/AST/Interp/comma.cpp b/clang/test/AST/ByteCode/comma.cpp similarity index 100% rename from clang/test/AST/Interp/comma.cpp rename to clang/test/AST/ByteCode/comma.cpp diff --git a/clang/test/AST/Interp/complex.c b/clang/test/AST/ByteCode/complex.c similarity index 100% rename from clang/test/AST/Interp/complex.c rename to clang/test/AST/ByteCode/complex.c diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/ByteCode/complex.cpp similarity index 100% rename from clang/test/AST/Interp/complex.cpp rename to clang/test/AST/ByteCode/complex.cpp diff --git a/clang/test/AST/Interp/cond.cpp b/clang/test/AST/ByteCode/cond.cpp similarity index 100% rename from clang/test/AST/Interp/cond.cpp rename to clang/test/AST/ByteCode/cond.cpp diff --git a/clang/test/AST/Interp/const-eval.c b/clang/test/AST/ByteCode/const-eval.c similarity index 100% rename from clang/test/AST/Interp/const-eval.c rename to clang/test/AST/ByteCode/const-eval.c diff --git a/clang/test/AST/Interp/const-fpfeatures.cpp b/clang/test/AST/ByteCode/const-fpfeatures.cpp similarity index 100% rename from clang/test/AST/Interp/const-fpfeatures.cpp rename to clang/test/AST/ByteCode/const-fpfeatures.cpp diff --git a/clang/test/AST/Interp/const-temporaries.cpp b/clang/test/AST/ByteCode/const-temporaries.cpp similarity index 100% rename from clang/test/AST/Interp/const-temporaries.cpp rename to clang/test/AST/ByteCode/const-temporaries.cpp diff --git a/clang/test/AST/Interp/constexpr-frame-describe.cpp b/clang/test/AST/ByteCode/constexpr-frame-describe.cpp similarity index 100% rename from clang/test/AST/Interp/constexpr-frame-describe.cpp rename to clang/test/AST/ByteCode/constexpr-frame-describe.cpp diff --git a/clang/test/AST/Interp/constexpr-nqueens.cpp b/clang/test/AST/ByteCode/constexpr-nqueens.cpp similarity index 100% rename from clang/test/AST/Interp/constexpr-nqueens.cpp rename to clang/test/AST/ByteCode/constexpr-nqueens.cpp diff --git a/clang/test/AST/Interp/constexpr-subobj-initialization.cpp b/clang/test/AST/ByteCode/constexpr-subobj-initialization.cpp similarity index 100% rename from clang/test/AST/Interp/constexpr-subobj-initialization.cpp rename to clang/test/AST/ByteCode/constexpr-subobj-initialization.cpp diff --git a/clang/test/AST/Interp/crash-GH49103-2.cpp b/clang/test/AST/ByteCode/crash-GH49103-2.cpp similarity index 100% rename from clang/test/AST/Interp/crash-GH49103-2.cpp rename to clang/test/AST/ByteCode/crash-GH49103-2.cpp diff --git a/clang/test/AST/Interp/cxx03.cpp b/clang/test/AST/ByteCode/cxx03.cpp similarity index 100% rename from clang/test/AST/Interp/cxx03.cpp rename to clang/test/AST/ByteCode/cxx03.cpp diff --git a/clang/test/AST/Interp/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp similarity index 100% rename from clang/test/AST/Interp/cxx11.cpp rename to clang/test/AST/ByteCode/cxx11.cpp diff --git a/clang/test/AST/Interp/cxx17.cpp b/clang/test/AST/ByteCode/cxx17.cpp similarity index 100% rename from clang/test/AST/Interp/cxx17.cpp rename to clang/test/AST/ByteCode/cxx17.cpp diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp similarity index 100% rename from clang/test/AST/Interp/cxx20.cpp rename to clang/test/AST/ByteCode/cxx20.cpp diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp similarity index 95% rename from clang/test/AST/Interp/cxx23.cpp rename to clang/test/AST/ByteCode/cxx23.cpp index eb05a9fda0dfb13..756eec5b8256053 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/ByteCode/cxx23.cpp @@ -224,3 +224,17 @@ namespace ExplicitLambdaInstancePointer { static_assert(fp(1) == 1, ""); } } + +namespace TwosComplementShifts { + using uint32 = __UINT32_TYPE__; + using int32 = __INT32_TYPE__; + static_assert(uint32(int32(0x1234) << 16) == 0x12340000); + static_assert(uint32(int32(0x1234) << 19) == 0x91a00000); + static_assert(uint32(int32(0x1234) << 20) == 0x23400000); + static_assert(uint32(int32(0x1234) << 24) == 0x34000000); + static_assert(uint32(int32(-1) << 31) == 0x80000000); + + static_assert(-2 >> 1 == -1); + static_assert(-3 >> 1 == -2); + static_assert(-7 >> 1 == -4); +} diff --git a/clang/test/AST/Interp/cxx26.cpp b/clang/test/AST/ByteCode/cxx26.cpp similarity index 100% rename from clang/test/AST/Interp/cxx26.cpp rename to clang/test/AST/ByteCode/cxx26.cpp diff --git a/clang/test/AST/Interp/cxx2a.cpp b/clang/test/AST/ByteCode/cxx2a.cpp similarity index 100% rename from clang/test/AST/Interp/cxx2a.cpp rename to clang/test/AST/ByteCode/cxx2a.cpp diff --git a/clang/test/AST/Interp/cxx98.cpp b/clang/test/AST/ByteCode/cxx98.cpp similarity index 100% rename from clang/test/AST/Interp/cxx98.cpp rename to clang/test/AST/ByteCode/cxx98.cpp diff --git a/clang/test/AST/Interp/depth-limit.cpp b/clang/test/AST/ByteCode/depth-limit.cpp similarity index 100% rename from clang/test/AST/Interp/depth-limit.cpp rename to clang/test/AST/ByteCode/depth-limit.cpp diff --git a/clang/test/AST/Interp/depth-limit2.cpp b/clang/test/AST/ByteCode/depth-limit2.cpp similarity index 100% rename from clang/test/AST/Interp/depth-limit2.cpp rename to clang/test/AST/ByteCode/depth-limit2.cpp diff --git a/clang/test/AST/Interp/enums-targets.cpp b/clang/test/AST/ByteCode/enums-targets.cpp similarity index 100% rename from clang/test/AST/Interp/enums-targets.cpp rename to clang/test/AST/ByteCode/enums-targets.cpp diff --git a/clang/test/AST/Interp/enums.cpp b/clang/test/AST/ByteCode/enums.cpp similarity index 90% rename from clang/test/AST/Interp/enums.cpp rename to clang/test/AST/ByteCode/enums.cpp index c4db7875451677e..459cf3a0c83d540 100644 --- a/clang/test/AST/Interp/enums.cpp +++ b/clang/test/AST/ByteCode/enums.cpp @@ -48,3 +48,8 @@ constexpr EC getB() { static_assert(getB() == EC::B, ""); + +namespace B { + enum E : bool { Zero, One }; + static_assert((int)(E)2 == 1, ""); +} // namespace B diff --git a/clang/test/AST/Interp/eval-order.cpp b/clang/test/AST/ByteCode/eval-order.cpp similarity index 100% rename from clang/test/AST/Interp/eval-order.cpp rename to clang/test/AST/ByteCode/eval-order.cpp diff --git a/clang/test/AST/Interp/floats.cpp b/clang/test/AST/ByteCode/floats.cpp similarity index 100% rename from clang/test/AST/Interp/floats.cpp rename to clang/test/AST/ByteCode/floats.cpp diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/ByteCode/functions.cpp similarity index 96% rename from clang/test/AST/Interp/functions.cpp rename to clang/test/AST/ByteCode/functions.cpp index f190262ad3ebee4..b00f59a8d8d433d 100644 --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/ByteCode/functions.cpp @@ -221,6 +221,17 @@ namespace Comparison { static_assert(pg == &g, ""); } + constexpr int Double(int n) { return 2 * n; } + constexpr int Triple(int n) { return 3 * n; } + constexpr int Twice(int (*F)(int), int n) { return F(F(n)); } + constexpr int Quadruple(int n) { return Twice(Double, n); } + constexpr auto Select(int n) -> int (*)(int) { + return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0; + } + constexpr int Apply(int (*F)(int), int n) { return F(n); } // both-note {{'F' evaluates to a null function pointer}} + + constexpr int Invalid = Apply(Select(0), 0); // both-error {{must be initialized by a constant expression}} \ + // both-note {{in call to 'Apply(nullptr, 0)'}} } struct F { diff --git a/clang/test/AST/Interp/hlsl.hlsl b/clang/test/AST/ByteCode/hlsl.hlsl similarity index 100% rename from clang/test/AST/Interp/hlsl.hlsl rename to clang/test/AST/ByteCode/hlsl.hlsl diff --git a/clang/test/AST/Interp/if.cpp b/clang/test/AST/ByteCode/if.cpp similarity index 100% rename from clang/test/AST/Interp/if.cpp rename to clang/test/AST/ByteCode/if.cpp diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/ByteCode/intap.cpp similarity index 100% rename from clang/test/AST/Interp/intap.cpp rename to clang/test/AST/ByteCode/intap.cpp diff --git a/clang/test/AST/Interp/invalid.cpp b/clang/test/AST/ByteCode/invalid.cpp similarity index 100% rename from clang/test/AST/Interp/invalid.cpp rename to clang/test/AST/ByteCode/invalid.cpp diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/ByteCode/lambda.cpp similarity index 100% rename from clang/test/AST/Interp/lambda.cpp rename to clang/test/AST/ByteCode/lambda.cpp diff --git a/clang/test/AST/Interp/lifetimes.cpp b/clang/test/AST/ByteCode/lifetimes.cpp similarity index 93% rename from clang/test/AST/Interp/lifetimes.cpp rename to clang/test/AST/ByteCode/lifetimes.cpp index 9fca54fe11120aa..9a99485c4a40bff 100644 --- a/clang/test/AST/Interp/lifetimes.cpp +++ b/clang/test/AST/ByteCode/lifetimes.cpp @@ -60,3 +60,11 @@ namespace MoveFnWorks { } static_assert(dtor_calls_dtor(), ""); } + +namespace PrimitiveMoveFn { + /// This used to crash. + void test() { + const float y = 100; + const float &x = y; + } +} diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/ByteCode/literals.cpp similarity index 100% rename from clang/test/AST/Interp/literals.cpp rename to clang/test/AST/ByteCode/literals.cpp diff --git a/clang/test/AST/Interp/loops.cpp b/clang/test/AST/ByteCode/loops.cpp similarity index 100% rename from clang/test/AST/Interp/loops.cpp rename to clang/test/AST/ByteCode/loops.cpp diff --git a/clang/test/AST/Interp/memberpointers.cpp b/clang/test/AST/ByteCode/memberpointers.cpp similarity index 94% rename from clang/test/AST/Interp/memberpointers.cpp rename to clang/test/AST/ByteCode/memberpointers.cpp index f38e94863863159..ea4a725d3fd0dfa 100644 --- a/clang/test/AST/Interp/memberpointers.cpp +++ b/clang/test/AST/ByteCode/memberpointers.cpp @@ -209,3 +209,20 @@ namespace MemPtrTemporary { static_assert(apply(A(), &A::f) == 5, ""); } + +namespace IndirectFields { + struct I { union { struct { int a, b; }; }; }; + + template + constexpr int ReadField(const T &o) { + return F ? o.*F : 0; + } + void ReadFields() { + I i; + ReadField(i); + ReadField(i); + } + + constexpr I i{12}; + static_assert(ReadField(i) == 12, ""); +} diff --git a/clang/test/AST/Interp/ms.cpp b/clang/test/AST/ByteCode/ms.cpp similarity index 100% rename from clang/test/AST/Interp/ms.cpp rename to clang/test/AST/ByteCode/ms.cpp diff --git a/clang/test/AST/Interp/mutable.cpp b/clang/test/AST/ByteCode/mutable.cpp similarity index 100% rename from clang/test/AST/Interp/mutable.cpp rename to clang/test/AST/ByteCode/mutable.cpp diff --git a/clang/test/AST/Interp/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp similarity index 100% rename from clang/test/AST/Interp/new-delete.cpp rename to clang/test/AST/ByteCode/new-delete.cpp diff --git a/clang/test/AST/Interp/nullable.cpp b/clang/test/AST/ByteCode/nullable.cpp similarity index 100% rename from clang/test/AST/Interp/nullable.cpp rename to clang/test/AST/ByteCode/nullable.cpp diff --git a/clang/test/AST/Interp/objc.mm b/clang/test/AST/ByteCode/objc.mm similarity index 100% rename from clang/test/AST/Interp/objc.mm rename to clang/test/AST/ByteCode/objc.mm diff --git a/clang/test/AST/Interp/opencl.cl b/clang/test/AST/ByteCode/opencl.cl similarity index 100% rename from clang/test/AST/Interp/opencl.cl rename to clang/test/AST/ByteCode/opencl.cl diff --git a/clang/test/AST/Interp/pointer-addition.c b/clang/test/AST/ByteCode/pointer-addition.c similarity index 100% rename from clang/test/AST/Interp/pointer-addition.c rename to clang/test/AST/ByteCode/pointer-addition.c diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/ByteCode/records.cpp similarity index 98% rename from clang/test/AST/Interp/records.cpp rename to clang/test/AST/ByteCode/records.cpp index f51f9771b38aaa6..7e3cf5b94518f7c 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1627,3 +1627,29 @@ namespace DtorDestroysFieldsAfterSelf { static_assert(foo() == 15); } #endif + +namespace ExprWithCleanups { + struct A { A(); ~A(); int get(); }; + constexpr int get() {return false ? A().get() : 1;} + static_assert(get() == 1, ""); + + + struct S { + int V; + constexpr S(int V) : V(V) {} + constexpr int get() { + return V; + } + }; + constexpr int get(bool b) { + S a = b ? S(1) : S(2); + + return a.get(); + } + static_assert(get(true) == 1, ""); + static_assert(get(false) == 2, ""); + + + constexpr auto F = true ? 1i : 2i; + static_assert(F == 1i, ""); +} diff --git a/clang/test/AST/Interp/references.cpp b/clang/test/AST/ByteCode/references.cpp similarity index 100% rename from clang/test/AST/Interp/references.cpp rename to clang/test/AST/ByteCode/references.cpp diff --git a/clang/test/AST/Interp/shifts.cpp b/clang/test/AST/ByteCode/shifts.cpp similarity index 100% rename from clang/test/AST/Interp/shifts.cpp rename to clang/test/AST/ByteCode/shifts.cpp diff --git a/clang/test/AST/Interp/spaceship.cpp b/clang/test/AST/ByteCode/spaceship.cpp similarity index 100% rename from clang/test/AST/Interp/spaceship.cpp rename to clang/test/AST/ByteCode/spaceship.cpp diff --git a/clang/test/AST/Interp/switch.cpp b/clang/test/AST/ByteCode/switch.cpp similarity index 100% rename from clang/test/AST/Interp/switch.cpp rename to clang/test/AST/ByteCode/switch.cpp diff --git a/clang/test/AST/Interp/sycl.cpp b/clang/test/AST/ByteCode/sycl.cpp similarity index 100% rename from clang/test/AST/Interp/sycl.cpp rename to clang/test/AST/ByteCode/sycl.cpp diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/ByteCode/unions.cpp similarity index 100% rename from clang/test/AST/Interp/unions.cpp rename to clang/test/AST/ByteCode/unions.cpp diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/ByteCode/vectors.cpp similarity index 100% rename from clang/test/AST/Interp/vectors.cpp rename to clang/test/AST/ByteCode/vectors.cpp diff --git a/clang/test/AST/Interp/weak.cpp b/clang/test/AST/ByteCode/weak.cpp similarity index 100% rename from clang/test/AST/Interp/weak.cpp rename to clang/test/AST/ByteCode/weak.cpp diff --git a/clang/test/AST/ast-dump-funcs-json.cpp b/clang/test/AST/ast-dump-funcs-json.cpp index 041d98f2713d32e..957df5cea6ec534 100644 --- a/clang/test/AST/ast-dump-funcs-json.cpp +++ b/clang/test/AST/ast-dump-funcs-json.cpp @@ -41,13 +41,18 @@ int main() { Test1(); // Causes this to be marked 'used' } +template +struct TestFriends { + friend Ts...; +}; + // NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 124, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 4, // CHECK-NEXT: "col": 8, @@ -55,12 +60,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 119, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 130, // CHECK-NEXT: "col": 14, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -76,7 +81,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 140, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 5, // CHECK-NEXT: "col": 8, @@ -84,12 +89,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 135, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 148, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 5 // CHECK-NEXT: } @@ -105,7 +110,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 162, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 6, // CHECK-NEXT: "col": 8, @@ -113,12 +118,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 157, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 170, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: } @@ -134,7 +139,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 187, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 7, // CHECK-NEXT: "col": 8, @@ -142,12 +147,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 182, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 195, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -163,7 +168,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 205, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 8, // CHECK-NEXT: "col": 8, @@ -171,12 +176,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 200, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 213, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: } @@ -192,7 +197,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 232, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 9, // CHECK-NEXT: "col": 16, @@ -200,12 +205,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 219, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 7 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 253, // CHECK-NEXT: "col": 37, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -221,18 +226,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 243, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 238, // CHECK-NEXT: "col": 22, // CHECK-NEXT: "tokLen": 5 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 238, // CHECK-NEXT: "col": 22, // CHECK-NEXT: "tokLen": 5 // CHECK-NEXT: } @@ -245,18 +250,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 249, // CHECK-NEXT: "col": 33, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 245, // CHECK-NEXT: "col": 29, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 251, // CHECK-NEXT: "col": 35, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: } @@ -271,12 +276,12 @@ int main() { // CHECK-NEXT: "kind": "IntegerLiteral", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 251, // CHECK-NEXT: "col": 35, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 251, // CHECK-NEXT: "col": 35, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: } @@ -296,7 +301,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 271, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 10, // CHECK-NEXT: "col": 16, @@ -304,12 +309,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 258, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 7 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 281, // CHECK-NEXT: "col": 26, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -327,7 +332,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 343, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 14, // CHECK-NEXT: "col": 8, @@ -335,12 +340,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 338, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 367, // CHECK-NEXT: "col": 32, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: } @@ -355,18 +360,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 354, // CHECK-NEXT: "col": 19, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 349, // CHECK-NEXT: "col": 14, // CHECK-NEXT: "tokLen": 5 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 349, // CHECK-NEXT: "col": 14, // CHECK-NEXT: "tokLen": 5 // CHECK-NEXT: } @@ -379,18 +384,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 360, // CHECK-NEXT: "col": 25, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 356, // CHECK-NEXT: "col": 21, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 362, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: } @@ -405,12 +410,12 @@ int main() { // CHECK-NEXT: "kind": "IntegerLiteral", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 362, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 362, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: } @@ -428,12 +433,12 @@ int main() { // CHECK-NEXT: "kind": "OverrideAttr", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 367, // CHECK-NEXT: "col": 32, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 367, // CHECK-NEXT: "col": 32, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: } @@ -446,7 +451,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 399, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 18, // CHECK-NEXT: "col": 8, @@ -454,12 +459,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 394, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 405, // CHECK-NEXT: "col": 14, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -475,7 +480,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "CXXMethodDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 419, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 20, // CHECK-NEXT: "col": 9, @@ -483,12 +488,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 411, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 428, // CHECK-NEXT: "col": 18, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -506,12 +511,12 @@ int main() { // CHECK-NEXT: "kind": "CompoundStmt", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 427, // CHECK-NEXT: "col": 17, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 428, // CHECK-NEXT: "col": 18, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -524,7 +529,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 446, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 22, // CHECK-NEXT: "col": 6, @@ -532,12 +537,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 441, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 452, // CHECK-NEXT: "col": 12, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -554,7 +559,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 460, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 23, // CHECK-NEXT: "col": 6, @@ -562,12 +567,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 455, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 470, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -583,7 +588,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 478, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 24, // CHECK-NEXT: "col": 6, @@ -591,12 +596,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 473, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 496, // CHECK-NEXT: "col": 24, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -611,18 +616,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 488, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 484, // CHECK-NEXT: "col": 12, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 488, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -636,18 +641,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 495, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 491, // CHECK-NEXT: "col": 19, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 495, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -664,7 +669,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 504, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 25, // CHECK-NEXT: "col": 6, @@ -672,12 +677,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 499, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 527, // CHECK-NEXT: "col": 29, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -692,18 +697,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 514, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 510, // CHECK-NEXT: "col": 12, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 514, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -717,18 +722,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 521, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 517, // CHECK-NEXT: "col": 19, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 525, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: } @@ -744,12 +749,12 @@ int main() { // CHECK-NEXT: "kind": "IntegerLiteral", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 525, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 525, // CHECK-NEXT: "col": 27, // CHECK-NEXT: "tokLen": 2 // CHECK-NEXT: } @@ -769,7 +774,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 545, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 26, // CHECK-NEXT: "col": 16, @@ -777,12 +782,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 530, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 9 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 555, // CHECK-NEXT: "col": 26, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -799,7 +804,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 570, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 27, // CHECK-NEXT: "col": 13, @@ -807,12 +812,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 558, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 6 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 580, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -829,7 +834,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 595, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 28, // CHECK-NEXT: "col": 13, @@ -837,12 +842,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 583, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 6 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 605, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -859,7 +864,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 620, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 29, // CHECK-NEXT: "col": 13, @@ -867,12 +872,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 608, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 6 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 630, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -889,7 +894,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 638, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 30, // CHECK-NEXT: "col": 6, @@ -897,12 +902,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 633, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 650, // CHECK-NEXT: "col": 18, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: } @@ -918,7 +923,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 665, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 31, // CHECK-NEXT: "col": 6, @@ -926,12 +931,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 660, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 692, // CHECK-NEXT: "col": 33, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -947,7 +952,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 700, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 32, // CHECK-NEXT: "col": 6, @@ -955,12 +960,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 695, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 723, // CHECK-NEXT: "col": 29, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -976,7 +981,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionTemplateDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 751, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 35, // CHECK-NEXT: "col": 3, @@ -984,13 +989,13 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 727, // CHECK-NEXT: "line": 34, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 760, // CHECK-NEXT: "line": 35, // CHECK-NEXT: "col": 12, // CHECK-NEXT: "tokLen": 1 @@ -1002,19 +1007,19 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "TemplateTypeParmDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 746, // CHECK-NEXT: "line": 34, // CHECK-NEXT: "col": 20, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 737, // CHECK-NEXT: "col": 11, // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 746, // CHECK-NEXT: "col": 20, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1029,19 +1034,19 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 751, // CHECK-NEXT: "line": 35, // CHECK-NEXT: "col": 3, // CHECK-NEXT: "tokLen": 6 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 749, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 760, // CHECK-NEXT: "col": 12, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1055,18 +1060,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 760, // CHECK-NEXT: "col": 12, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 758, // CHECK-NEXT: "col": 10, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 759, // CHECK-NEXT: "col": 11, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1084,7 +1089,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 769, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 37, // CHECK-NEXT: "col": 6, @@ -1092,12 +1097,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 764, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 782, // CHECK-NEXT: "col": 19, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1112,18 +1117,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 779, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 776, // CHECK-NEXT: "col": 13, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 776, // CHECK-NEXT: "col": 13, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: } @@ -1137,12 +1142,12 @@ int main() { // CHECK-NEXT: "kind": "CompoundStmt", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 781, // CHECK-NEXT: "col": 18, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 782, // CHECK-NEXT: "col": 19, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1155,7 +1160,7 @@ int main() { // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 789, // CHECK-NEXT: "file": "{{.*}}", // CHECK-NEXT: "line": 38, // CHECK-NEXT: "col": 6, @@ -1163,12 +1168,12 @@ int main() { // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 784, // CHECK-NEXT: "col": 1, // CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 807, // CHECK-NEXT: "col": 24, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1184,18 +1189,18 @@ int main() { // CHECK-NEXT: "id": "0x{{.*}}", // CHECK-NEXT: "kind": "ParmVarDecl", // CHECK-NEXT: "loc": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 799, // CHECK-NEXT: "col": 16, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 796, // CHECK-NEXT: "col": 13, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 796, // CHECK-NEXT: "col": 13, // CHECK-NEXT: "tokLen": 3 // CHECK-NEXT: } @@ -1209,12 +1214,12 @@ int main() { // CHECK-NEXT: "kind": "CompoundStmt", // CHECK-NEXT: "range": { // CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 806, // CHECK-NEXT: "col": 23, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": {{[0-9]+}}, +// CHECK-NEXT: "offset": 807, // CHECK-NEXT: "col": 24, // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } @@ -1222,3 +1227,189 @@ int main() { // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } + + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "ClassTemplateDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 905, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 45, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 11 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 872, +// CHECK-NEXT: "line": 44, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 8 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 937, +// CHECK-NEXT: "line": 47, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "TestFriends", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 894, +// CHECK-NEXT: "line": 44, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 882, +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "tokLen": 8 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 894, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 2 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "Ts", +// CHECK-NEXT: "tagUsed": "typename", +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "isParameterPack": true +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 905, +// CHECK-NEXT: "line": 45, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 11 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 898, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 937, +// CHECK-NEXT: "line": 47, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "TestFriends", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canConstDefaultInit": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "defaultedIsConstexpr": true, +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "isConstexpr": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "irrelevant": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "hasConstexprNonCopyMoveConstructor": true, +// CHECK-NEXT: "isAggregate": true, +// CHECK-NEXT: "isEmpty": true, +// CHECK-NEXT: "isLiteral": true, +// CHECK-NEXT: "isPOD": true, +// CHECK-NEXT: "isStandardLayout": true, +// CHECK-NEXT: "isTrivial": true, +// CHECK-NEXT: "isTriviallyCopyable": true, +// CHECK-NEXT: "moveAssign": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "moveCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 905, +// CHECK-NEXT: "line": 45, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 11 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 898, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 905, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 11 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "TestFriends", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FriendDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 930, +// CHECK-NEXT: "line": 46, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 923, +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 932, +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "Ts" +// CHECK-NEXT: }, +// CHECK-NEXT: "isPackExpansion": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } diff --git a/clang/test/AST/cxx2c-variadic-friends.cpp b/clang/test/AST/cxx2c-variadic-friends.cpp new file mode 100644 index 000000000000000..fc84e7346fe0364 --- /dev/null +++ b/clang/test/AST/cxx2c-variadic-friends.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-dump -std=c++2c %s | FileCheck %s +// RUN: %clang_cc1 -ast-print -std=c++2c %s | FileCheck %s --check-prefix=PRINT +// RUN: %clang_cc1 -emit-pch -std=c++2c -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++2c -include-pch %t -ast-dump-all /dev/null + +struct S; +template struct TS; // #template + +// CHECK-LABEL: CXXRecordDecl {{.*}} struct Friends +// PRINT-LABEL: struct Friends { +struct Friends { + // CHECK: FriendDecl {{.*}} 'int' + // CHECK-NEXT: FriendDecl {{.*}} 'long' + // PRINT-NEXT: friend int; + // PRINT-NEXT: friend long; + friend int, long; + + // CHECK-NEXT: FriendDecl {{.*}} 'int' + // CHECK-NEXT: FriendDecl {{.*}} 'long' + // CHECK-NEXT: FriendDecl {{.*}} 'char' + // PRINT-NEXT: friend int; + // PRINT-NEXT: friend long; + // PRINT-NEXT: friend char; + friend int, long, char; + + // CHECK-NEXT: FriendDecl {{.*}} 'S' + // PRINT-NEXT: friend S; + friend S; + + // CHECK-NEXT: FriendDecl {{.*}} 'S' + // CHECK-NEXT: FriendDecl {{.*}} 'S' + // CHECK-NEXT: FriendDecl {{.*}} 'S' + // PRINT-NEXT: friend S; + // PRINT-NEXT: friend S; + // PRINT-NEXT: friend S; + friend S, S, S; + + // CHECK-NEXT: FriendDecl + // CHECK-NEXT: ClassTemplateDecl {{.*}} friend TS + // PRINT-NEXT: friend template struct TS; + template friend struct TS; +}; + +namespace specialisations { +template +struct C { + template struct Nested; +}; + +struct N { + template class C; +}; + +// CHECK-LABEL: ClassTemplateDecl {{.*}} Variadic +// PRINT-LABEL: template struct Variadic { +template struct Variadic { + // CHECK: FriendDecl {{.*}} 'Pack'... + // CHECK-NEXT: FriendDecl {{.*}} 'long' + // CHECK-NEXT: FriendDecl {{.*}} 'Pack'... + // PRINT-NEXT: friend Pack...; + // PRINT-NEXT: friend long; + // PRINT-NEXT: friend Pack...; + friend Pack..., long, Pack...; + + // CHECK-NEXT: FriendDecl {{.*}} 'TS'... + // PRINT-NEXT: friend TS...; + friend TS...; +}; + +// CHECK-LABEL: ClassTemplateDecl {{.*}} S2 +// PRINT-LABEL: template struct S2 { +template struct S2 { + // CHECK: FriendDecl {{.*}} 'class C':'C'... + // PRINT-NEXT: friend class C...; + friend class C...; + + // CHECK-NEXT: FriendDecl {{.*}} 'class N::C':'C'... + // PRINT-NEXT: friend class N::C... + friend class N::C...; +}; +} diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp index 1180063502168f8..3181aea870c8aad 100644 --- a/clang/test/Analysis/asm.cpp +++ b/clang/test/Analysis/asm.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify +// RUN: %clang_analyze_cc1 -triple=x86_64-unknown-unknown \ +// RUN: -analyzer-checker debug.ExprInspection,core -fheinous-gnu-extensions -w %s -verify int clang_analyzer_eval(int); @@ -10,3 +11,32 @@ void testRValueOutput() { clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(ref == 1); // expected-warning{{UNKNOWN}} } + +void *MyMemcpy(void *d, const void *s, const int n) { + asm volatile ( + "cld\n rep movsb\n" + :: "S" (s), "D" (d), "c" (n) : "memory" + ); + return d; +} + +void testInlineAsmMemcpy(void) +{ + int a, b = 10, c; + MyMemcpy(&a, &b, sizeof(b)); + c = a; // no-warning +} + +void testInlineAsmMemcpyArray(void) +{ + int a[10], b[10] = {}, c; + MyMemcpy(&a, &b, sizeof(b)); + c = a[8]; // no-warning +} + +void testInlineAsmMemcpyUninit(void) +{ + int a[10], b[10] = {}, c; + MyMemcpy(&a[1], &b[1], sizeof(b) - sizeof(b[1])); + c = a[0]; // expected-warning{{Assigned value is garbage or undefined}} +} diff --git a/clang/test/Analysis/builtin_signbit.cpp b/clang/test/Analysis/builtin_signbit.cpp index be10f0950f69b7c..ad185d855cfff30 100644 --- a/clang/test/Analysis/builtin_signbit.cpp +++ b/clang/test/Analysis/builtin_signbit.cpp @@ -12,103 +12,83 @@ long double ld = -1.0L; // CHECK-BE32-LABEL: define dso_local void @_Z12test_signbitv( // CHECK-BE32-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-BE32-NEXT: entry: -// CHECK-BE32-NEXT: [[TMP0:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64 -// CHECK-BE32-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i64 -// CHECK-BE32-NEXT: [[TMP2:%.*]] = icmp slt i64 [[TMP1]], 0 -// CHECK-BE32-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP2]] to i8 +// CHECK-BE32-NEXT: store i8 0, ptr @b, align 1 +// CHECK-BE32-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-BE32-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128 +// CHECK-BE32-NEXT: [[TMP2:%.*]] = lshr i128 [[TMP1]], 64 +// CHECK-BE32-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64 +// CHECK-BE32-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0 +// CHECK-BE32-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP4]] to i8 // CHECK-BE32-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1 -// CHECK-BE32-NEXT: [[TMP3:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-BE32-NEXT: [[TMP4:%.*]] = bitcast ppc_fp128 [[TMP3]] to i128 -// CHECK-BE32-NEXT: [[TMP5:%.*]] = lshr i128 [[TMP4]], 64 -// CHECK-BE32-NEXT: [[TMP6:%.*]] = trunc i128 [[TMP5]] to i64 -// CHECK-BE32-NEXT: [[TMP7:%.*]] = icmp slt i64 [[TMP6]], 0 +// CHECK-BE32-NEXT: store i8 0, ptr @b, align 1 +// CHECK-BE32-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8 +// CHECK-BE32-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float +// CHECK-BE32-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32 +// CHECK-BE32-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0 // CHECK-BE32-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP7]] to i8 // CHECK-BE32-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1 // CHECK-BE32-NEXT: store i8 0, ptr @b, align 1 -// CHECK-BE32-NEXT: [[TMP8:%.*]] = load double, ptr @d, align 8 -// CHECK-BE32-NEXT: [[CONV:%.*]] = fptrunc double [[TMP8]] to float -// CHECK-BE32-NEXT: [[TMP9:%.*]] = bitcast float [[CONV]] to i32 -// CHECK-BE32-NEXT: [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0 -// CHECK-BE32-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP10]] to i8 +// CHECK-BE32-NEXT: [[TMP8:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-BE32-NEXT: [[TMP9:%.*]] = bitcast ppc_fp128 [[TMP8]] to i128 +// CHECK-BE32-NEXT: [[TMP10:%.*]] = lshr i128 [[TMP9]], 64 +// CHECK-BE32-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64 +// CHECK-BE32-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0 +// CHECK-BE32-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP12]] to i8 // CHECK-BE32-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1 -// CHECK-BE32-NEXT: [[TMP11:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64 -// CHECK-BE32-NEXT: [[TMP12:%.*]] = trunc i128 [[TMP11]] to i64 -// CHECK-BE32-NEXT: [[TMP13:%.*]] = icmp slt i64 [[TMP12]], 0 -// CHECK-BE32-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP13]] to i8 -// CHECK-BE32-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1 -// CHECK-BE32-NEXT: [[TMP14:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-BE32-NEXT: [[TMP15:%.*]] = bitcast ppc_fp128 [[TMP14]] to i128 -// CHECK-BE32-NEXT: [[TMP16:%.*]] = lshr i128 [[TMP15]], 64 -// CHECK-BE32-NEXT: [[TMP17:%.*]] = trunc i128 [[TMP16]] to i64 -// CHECK-BE32-NEXT: [[TMP18:%.*]] = icmp slt i64 [[TMP17]], 0 -// CHECK-BE32-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP18]] to i8 -// CHECK-BE32-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1 // CHECK-BE32-NEXT: ret void // // CHECK-BE64-LABEL: define dso_local void @_Z12test_signbitv( // CHECK-BE64-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-BE64-NEXT: entry: -// CHECK-BE64-NEXT: [[TMP0:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64 -// CHECK-BE64-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i64 -// CHECK-BE64-NEXT: [[TMP2:%.*]] = icmp slt i64 [[TMP1]], 0 -// CHECK-BE64-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP2]] to i8 +// CHECK-BE64-NEXT: store i8 0, ptr @b, align 1 +// CHECK-BE64-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-BE64-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128 +// CHECK-BE64-NEXT: [[TMP2:%.*]] = lshr i128 [[TMP1]], 64 +// CHECK-BE64-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64 +// CHECK-BE64-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0 +// CHECK-BE64-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP4]] to i8 // CHECK-BE64-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1 -// CHECK-BE64-NEXT: [[TMP3:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-BE64-NEXT: [[TMP4:%.*]] = bitcast ppc_fp128 [[TMP3]] to i128 -// CHECK-BE64-NEXT: [[TMP5:%.*]] = lshr i128 [[TMP4]], 64 -// CHECK-BE64-NEXT: [[TMP6:%.*]] = trunc i128 [[TMP5]] to i64 -// CHECK-BE64-NEXT: [[TMP7:%.*]] = icmp slt i64 [[TMP6]], 0 +// CHECK-BE64-NEXT: store i8 0, ptr @b, align 1 +// CHECK-BE64-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8 +// CHECK-BE64-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float +// CHECK-BE64-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32 +// CHECK-BE64-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0 // CHECK-BE64-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP7]] to i8 // CHECK-BE64-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1 // CHECK-BE64-NEXT: store i8 0, ptr @b, align 1 -// CHECK-BE64-NEXT: [[TMP8:%.*]] = load double, ptr @d, align 8 -// CHECK-BE64-NEXT: [[CONV:%.*]] = fptrunc double [[TMP8]] to float -// CHECK-BE64-NEXT: [[TMP9:%.*]] = bitcast float [[CONV]] to i32 -// CHECK-BE64-NEXT: [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0 -// CHECK-BE64-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP10]] to i8 +// CHECK-BE64-NEXT: [[TMP8:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-BE64-NEXT: [[TMP9:%.*]] = bitcast ppc_fp128 [[TMP8]] to i128 +// CHECK-BE64-NEXT: [[TMP10:%.*]] = lshr i128 [[TMP9]], 64 +// CHECK-BE64-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64 +// CHECK-BE64-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0 +// CHECK-BE64-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP12]] to i8 // CHECK-BE64-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1 -// CHECK-BE64-NEXT: [[TMP11:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64 -// CHECK-BE64-NEXT: [[TMP12:%.*]] = trunc i128 [[TMP11]] to i64 -// CHECK-BE64-NEXT: [[TMP13:%.*]] = icmp slt i64 [[TMP12]], 0 -// CHECK-BE64-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP13]] to i8 -// CHECK-BE64-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1 -// CHECK-BE64-NEXT: [[TMP14:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-BE64-NEXT: [[TMP15:%.*]] = bitcast ppc_fp128 [[TMP14]] to i128 -// CHECK-BE64-NEXT: [[TMP16:%.*]] = lshr i128 [[TMP15]], 64 -// CHECK-BE64-NEXT: [[TMP17:%.*]] = trunc i128 [[TMP16]] to i64 -// CHECK-BE64-NEXT: [[TMP18:%.*]] = icmp slt i64 [[TMP17]], 0 -// CHECK-BE64-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP18]] to i8 -// CHECK-BE64-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1 // CHECK-BE64-NEXT: ret void // // CHECK-LE-LABEL: define dso_local void @_Z12test_signbitv( // CHECK-LE-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-LE-NEXT: entry: -// CHECK-LE-NEXT: [[TMP0:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0 -// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP0]] to i8 +// CHECK-LE-NEXT: store i8 0, ptr @b, align 1 +// CHECK-LE-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-LE-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128 +// CHECK-LE-NEXT: [[TMP2:%.*]] = trunc i128 [[TMP1]] to i64 +// CHECK-LE-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 0 +// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP3]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-LE-NEXT: [[TMP2:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128 -// CHECK-LE-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64 -// CHECK-LE-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0 -// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP4]] to i8 +// CHECK-LE-NEXT: store i8 0, ptr @b, align 1 +// CHECK-LE-NEXT: [[TMP4:%.*]] = load double, ptr @d, align 8 +// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP4]] to float +// CHECK-LE-NEXT: [[TMP5:%.*]] = bitcast float [[CONV]] to i32 +// CHECK-LE-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 0 +// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP6]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1 // CHECK-LE-NEXT: store i8 0, ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8 -// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float -// CHECK-LE-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32 -// CHECK-LE-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0 -// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP7]] to i8 +// CHECK-LE-NEXT: [[TMP7:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-LE-NEXT: [[TMP8:%.*]] = bitcast ppc_fp128 [[TMP7]] to i128 +// CHECK-LE-NEXT: [[TMP9:%.*]] = trunc i128 [[TMP8]] to i64 +// CHECK-LE-NEXT: [[TMP10:%.*]] = icmp slt i64 [[TMP9]], 0 +// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP10]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP8:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0 -// CHECK-LE-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP8]] to i8 -// CHECK-LE-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP9:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-LE-NEXT: [[TMP10:%.*]] = bitcast ppc_fp128 [[TMP9]] to i128 -// CHECK-LE-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64 -// CHECK-LE-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0 -// CHECK-LE-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP12]] to i8 -// CHECK-LE-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1 // CHECK-LE-NEXT: ret void // void test_signbit() diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp index d23d00ccdeebc1b..497a9328c115618 100644 --- a/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp @@ -11,6 +11,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s -DTEST11 // RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s -DTEST12 // RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s -DTEST13 +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s -DTEST14 +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm-only -verify -pedantic %s -DTEST15 #if TEST1 int main; // expected-error{{main cannot be declared as a variable in the global scope}} @@ -78,12 +80,14 @@ namespace ns { extern "C" struct A { int main(); }; // ok namespace c { - extern "C" void main(); // expected-warning {{'main' should not be 'extern "C"'}} + extern "C" void main(); // expected-error {{'main' must return 'int'}} \ + // expected-warning {{'main' should not be 'extern "C"'}} } extern "C" { namespace Z { - void main(); // expected-warning {{'main' should not be 'extern "C"'}} + void main(); // expected-error {{'main' must return 'int'}} \ + // expected-warning {{'main' should not be 'extern "C"'}} } } @@ -102,11 +106,6 @@ extern "C++" { int main(); // expected-warning {{'main' should not be 'extern "C++"'}} } -extern "C" { - int main(); // expected-warning {{'main' should not be 'extern "C"'}} -} - -extern "C" int main(); // expected-warning {{'main' should not be 'extern "C"'}} extern "C++" int main(); // expected-warning {{'main' should not be 'extern "C++"'}} namespace ns1 { @@ -122,6 +121,21 @@ namespace ns2 { extern "C++" void main() {} // ok } +#elif TEST14 +extern "C" { + int main(); // expected-warning {{'main' should not be 'extern "C"'}} +} + +extern "C" int main(); // expected-warning {{'main' should not be 'extern "C"'}} + +#elif TEST15 +extern "C" __attribute__((visibility("default"))) __attribute__((weak)) +int main(); // expected-warning {{'main' should not be 'extern "C"'}} + +unsigned long g() { + return reinterpret_cast(&main); // expected-warning {{referring to 'main' within an expression is a Clang extension}} +} + #else #error Unknown Test #endif diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp index ddf82f432c2eab0..a195e0548152d6c 100644 --- a/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp +++ b/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp @@ -16,6 +16,8 @@ struct A { bool operator<(const A&) const; bool operator<=(const A&) const = default; bool operator==(const A&) const && = default; // expected-error {{ref-qualifier '&&' is not allowed on a defaulted comparison operator}} + bool operator<=(const A&&) const = default; // expected-error {{invalid parameter type for defaulted relational comparison operator; found 'const A &&', expected 'const A &'}} + bool operator<=(const int&) const = default; // expected-error {{invalid parameter type for defaulted relational comparison operator; found 'const int &', expected 'const A &'}} bool operator>=(const A&) const volatile = default; // expected-error {{defaulted comparison function must not be volatile}} bool operator<=>(const A&) = default; // expected-error {{defaulted member three-way comparison operator must be const-qualified}} bool operator>=(const B&) const = default; // expected-error-re {{invalid parameter type for defaulted relational comparison operator; found 'const B &', expected 'const A &'{{$}}}} diff --git a/clang/test/CXX/drs/cwg20xx.cpp b/clang/test/CXX/drs/cwg20xx.cpp index cd2f26360d40215..b2dc5a9865e382c 100644 --- a/clang/test/CXX/drs/cwg20xx.cpp +++ b/clang/test/CXX/drs/cwg20xx.cpp @@ -401,11 +401,34 @@ namespace cwg2083 { // cwg2083: partial #endif } -namespace cwg2091 { // cwg2091: 2.7 +namespace cwg2091 { // cwg2091: 10 template struct X; template void f(X&); int n; void g(X &x) { f(x); } + +namespace GH42233 { +enum E { I }; + +class AA { }; +E EV[1] = {I}; + +template +struct S +{ + template< class E, const E* const V> + friend AA& operator<<( AA& os, const S& e ); +}; + +int f() +{ + S< E, EV > x; + + AA a; + a << x; + return 0; +} +} // namespace GH42233 } // namespace cwg2091 namespace cwg2094 { // cwg2094: 5 diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp index 0d9f5eac23866a2..1924008f15ba580 100644 --- a/clang/test/CXX/drs/cwg25xx.cpp +++ b/clang/test/CXX/drs/cwg25xx.cpp @@ -92,6 +92,30 @@ using ::cwg2521::operator""_div; #endif } // namespace cwg2521 +namespace cwg2547 { // cwg2547: 20 +#if __cplusplus >= 202302L +struct S; +// since-cxx23-note@-1 {{forward declaration of 'cwg2547::S'}} +// since-cxx23-note@-2 {{forward declaration of 'cwg2547::S'}} +// since-cxx23-note@-3 {{forward declaration of 'cwg2547::S'}} +bool operator==(S, S) = default; // error: S is not complete +// since-cxx23-error@-1 {{variable has incomplete type 'S'}} +// since-cxx23-error@-2 {{variable has incomplete type 'S'}} +// since-cxx23-error@-3 {{equality comparison operator is not a friend of incomplete class 'cwg2547::S'}} +struct S { + friend bool operator==(S, const S&) = default; // error: parameters of different types + // since-cxx23-error@-1 {{parameters for defaulted equality comparison operator must have the same type (found 'S' vs 'const S &')}} +}; +enum E { }; +bool operator==(E, E) = default; // error: not a member or friend of a class +// since-cxx23-error@-1 {{invalid parameter type for non-member defaulted equality comparison operator; found 'E', expected class or reference to a constant class}} + +struct S2 { + bool operator==(this int, S2) = default; + // since-cxx23-error@-1 {{invalid parameter type for defaulted equality comparison operator; found 'int', expected 'const cwg2547::S2 &'}} +}; +#endif +} // namespace cwg2547 #if __cplusplus >= 202302L namespace cwg2553 { // cwg2553: 18 review 2023-07-14 @@ -253,6 +277,41 @@ static_assert(__is_layout_compatible(U, V), ""); #endif } // namespace cwg2583 +namespace cwg2586 { // cwg2586: 20 +#if __cplusplus >= 202302L +struct X { + X& operator=(this X&, const X&) = default; + X& operator=(this X&, X&) = default; + X& operator=(this X&&, X&&) = default; + // FIXME: The notes could be clearer on *how* the type differs + // e.g., "if an explicit object parameter is used it must be of type reference to 'X'" + X& operator=(this int, const X&) = default; + // since-cxx23-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}} + // since-cxx23-note@-2 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}} + X& operator=(this X, const X&) = default; + // since-cxx23-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}} + // since-cxx23-note@-2 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}} +}; +struct Y { + void operator=(this int, const Y&); // This is copy constructor, suppresses implicit declaration +}; +static_assert([]{ + return !requires(T t, const T& ct) { t = ct; }; +}()); + +struct Z { + bool operator==(this const Z&, const Z&) = default; + bool operator==(this Z, Z) = default; + bool operator==(this Z, const Z&) = default; + // since-cxx23-error@-1 {{parameters for defaulted equality comparison operator must have the same type (found 'Z' vs 'const Z &')}} + bool operator==(this const Z&, Z) = default; + // since-cxx23-error@-1 {{parameters for defaulted equality comparison operator must have the same type (found 'const Z &' vs 'Z')}} + bool operator==(this int, Z) = default; + // since-cxx23-error@-1 {{invalid parameter type for defaulted equality comparison operator; found 'int', expected 'const cwg2586::Z &'}} +}; +#endif +} // namespace cwg2586 + namespace cwg2598 { // cwg2598: 18 #if __cplusplus >= 201103L struct NonLiteral { diff --git a/clang/test/CXX/drs/cwg29xx.cpp b/clang/test/CXX/drs/cwg29xx.cpp new file mode 100644 index 000000000000000..8cac9f283980b6b --- /dev/null +++ b/clang/test/CXX/drs/cwg29xx.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++98 -pedantic-errors -verify=expected,cxx98 %s +// RUN: %clang_cc1 -std=c++11 -pedantic-errors -verify=expected %s +// RUN: %clang_cc1 -std=c++14 -pedantic-errors -verify=expected %s +// RUN: %clang_cc1 -std=c++17 -pedantic-errors -verify=expected %s +// RUN: %clang_cc1 -std=c++20 -pedantic-errors -verify=expected %s +// RUN: %clang_cc1 -std=c++23 -pedantic-errors -verify=expected %s +// RUN: %clang_cc1 -std=c++2c -pedantic-errors -verify=expected %s + +namespace cwg2917 { // cwg2917: 20 open 2024-07-30 +template +class Foo; + +template // cxx98-error {{variadic templates are a C++11 extension}} +struct C { + struct Nested { }; +}; + +struct S { + template + friend class Foo, int; // expected-error {{a friend declaration that befriends a template must contain exactly one type-specifier}} + + template // cxx98-error {{variadic templates are a C++11 extension}} + friend class C::Nested...; // expected-error {{friend declaration expands pack 'Ts' that is declared it its own template parameter list}} +}; +} // namespace cwg2917 diff --git a/clang/test/CodeGen/PowerPC/transparent_union.c b/clang/test/CodeGen/PowerPC/transparent_union.c new file mode 100644 index 000000000000000..968a385c0ee45fe --- /dev/null +++ b/clang/test/CodeGen/PowerPC/transparent_union.c @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -O2 -target-cpu pwr7 \ +// RUN: -emit-llvm -fshort-enums %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-64 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux -O2 -target-cpu pwr7 \ +// RUN: -emit-llvm -fshort-enums %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-64 +// RUN: %clang_cc1 -triple powerpc-unknown-linux -O2 -target-cpu pwr7 \ +// RUN: -emit-llvm -fshort-enums %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-32 +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -O2 -target-cpu pwr7 \ +// RUN: -emit-llvm -fshort-enums %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-64 +// RUN: %clang_cc1 -triple powerpc-unknown-aix -O2 -target-cpu pwr7 \ +// RUN: -emit-llvm -fshort-enums %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-32 + +typedef union tu_c { + signed char a; + signed char b; +} tu_c_t __attribute__((transparent_union)); + +typedef union tu_s { + short a; +} tu_s_t __attribute__((transparent_union)); + +typedef union tu_us { + unsigned short a; +} tu_us_t __attribute__((transparent_union)); + +typedef union tu_l { + long a; +} tu_l_t __attribute__((transparent_union)); + +// CHECK-LABEL: define{{.*}} void @ftest0( +// CHECK-SAME: i8 noundef signext [[UC_COERCE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret void +void ftest0(tu_c_t uc) { } + +// CHECK-LABEL: define{{.*}} void @ftest1( +// CHECK-SAME: i16 noundef signext [[UC_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret void +void ftest1(tu_s_t uc) { } + +// CHECK-LABEL: define{{.*}} void @ftest2( +// CHECK-SAME: i16 noundef zeroext [[UC_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret void +void ftest2(tu_us_t uc) { } + +// CHECK-64-LABEL: define{{.*}} void @ftest3( +// CHECK-64-SAME: i64 [[UC_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-64-NEXT: [[ENTRY:.*:]] +// CHECK-64-NEXT: ret void +// +// CHECK-32-LABEL: define{{.*}} void @ftest3( +// CHECK-32-SAME: i32 [[UC_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-32-NEXT: [[ENTRY:.*:]] +// CHECK-32-NEXT: ret void +void ftest3(tu_l_t uc) { } + +typedef union etest { + enum flag {red, yellow, blue} fl; + enum weekend {sun, sat} b; +} etest_t __attribute__((transparent_union)); + +// CHECK-LABEL: define{{.*}} void @ftest4( +// CHECK-SAME: i8 noundef zeroext [[A_COERCE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret void +void ftest4(etest_t a) {} diff --git a/clang/test/CodeGen/RISCV/riscv-sdata-module-flag.c b/clang/test/CodeGen/RISCV/riscv-sdata-module-flag.c index 9bd69e7995877e4..83beabe85b1f4dd 100644 --- a/clang/test/CodeGen/RISCV/riscv-sdata-module-flag.c +++ b/clang/test/CodeGen/RISCV/riscv-sdata-module-flag.c @@ -21,23 +21,19 @@ // RUN: | FileCheck %s -check-prefix=RV64-S2G4 // RUN: %clang --target=riscv64-unknown-elf %s -S -emit-llvm -msmall-data-threshold=16 -o - \ // RUN: | FileCheck %s -check-prefix=RV64-T16 -// RUN: %clang --target=riscv64-linux-android %s -S -emit-llvm -o - \ -// RUN: | FileCheck %s -check-prefix=RV64-ANDROID -// RUN: %clang --target=riscv64-linux-android %s -S -emit-llvm -msmall-data-limit=8 -o - \ -// RUN: | FileCheck %s -check-prefix=RV64-ANDROID // RUN: %clang --target=riscv64-unknown-elf %s -S -emit-llvm -fpic -o - \ // RUN: | FileCheck %s -check-prefix=RV64-PIC void test(void) {} -// RV32-DEFAULT: !{i32 8, !"SmallDataLimit", i32 8} +// RV32-DEFAULT: !{i32 8, !"SmallDataLimit", i32 0} // RV32-G4: !{i32 8, !"SmallDataLimit", i32 4} // RV32-S0: !{i32 8, !"SmallDataLimit", i32 0} // RV32-S2G4: !{i32 8, !"SmallDataLimit", i32 4} // RV32-T16: !{i32 8, !"SmallDataLimit", i32 16} // RV32-PIC: !{i32 8, !"SmallDataLimit", i32 0} -// RV64-DEFAULT: !{i32 8, !"SmallDataLimit", i32 8} +// RV64-DEFAULT: !{i32 8, !"SmallDataLimit", i32 0} // RV64-G4: !{i32 8, !"SmallDataLimit", i32 4} // RV64-S0: !{i32 8, !"SmallDataLimit", i32 0} // RV64-S2G4: !{i32 8, !"SmallDataLimit", i32 4} @@ -48,6 +44,3 @@ void test(void) {} // The value will be passed by module flag instead of target feature. // RV32-S0-NOT: +small-data-limit= // RV64-S0-NOT: +small-data-limit= - -// RV64-ANDROID-NOT: small-data-limit -// RV64-ANDROID: !{i32 8, !"SmallDataLimit", i32 0} diff --git a/clang/test/CodeGen/aarch64-elf-pauthabi.c b/clang/test/CodeGen/aarch64-elf-pauthabi.c index d60dcee3618887e..023fa8c18e1300b 100644 --- a/clang/test/CodeGen/aarch64-elf-pauthabi.c +++ b/clang/test/CodeGen/aarch64-elf-pauthabi.c @@ -1,3 +1,5 @@ +//// TODO: also test with -fptrauth-elf-got when the driver flag is supported + // RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ // RUN: -fptrauth-intrinsics \ // RUN: -fptrauth-calls \ @@ -5,8 +7,11 @@ // RUN: -fptrauth-auth-traps \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ -// RUN: -fptrauth-init-fini %s \ -// RUN: -fptrauth-init-fini-address-discrimination %s | \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-init-fini-address-discrimination \ +// RUN: -fptrauth-indirect-gotos \ +// RUN: -fptrauth-type-info-vtable-pointer-discrimination \ +// RUN: -fptrauth-function-pointer-type-discrimination %s | \ // RUN: FileCheck %s --check-prefix=ALL // RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ @@ -37,8 +42,19 @@ // RUN: -fptrauth-calls -fptrauth-init-fini -fptrauth-init-fini-address-discrimination %s | \ // RUN: FileCheck %s --check-prefix=INITFINIADDR +// RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ +// RUN: -fptrauth-indirect-gotos %s | FileCheck %s --check-prefix=GOTOS + +// RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ +// RUN: -fptrauth-calls -fptrauth-type-info-vtable-pointer-discrimination %s | \ +// RUN: FileCheck %s --check-prefix=TYPEINFO + +// RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ +// RUN: -fptrauth-calls -fptrauth-function-pointer-type-discrimination %s | \ +// RUN: FileCheck %s --check-prefix=FPTRTYPE + // ALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} -// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 255} +// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 3839} // INTRIN: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} // INTRIN: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1} @@ -64,4 +80,13 @@ // INITFINIADDR: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} // INITFINIADDR: !{i32 1, !"aarch64-elf-pauthabi-version", i32 194} +// GOTOS: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// GOTOS: !{i32 1, !"aarch64-elf-pauthabi-version", i32 512} + +// TYPEINFO: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// TYPEINFO: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1026} + +// FPTRTYPE: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// FPTRTYPE: !{i32 1, !"aarch64-elf-pauthabi-version", i32 2050} + void foo() {} diff --git a/clang/test/CodeGen/aarch64-targetattr.c b/clang/test/CodeGen/aarch64-targetattr.c index 4f891f938b61860..d6227be2ebef83d 100644 --- a/clang/test/CodeGen/aarch64-targetattr.c +++ b/clang/test/CodeGen/aarch64-targetattr.c @@ -195,19 +195,19 @@ void minusarch() {} // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" } // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+v8.1a,+v8.2a,+v8a" } // CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8a" } -// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" } -// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+ete,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm,+trbe,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+predres,+ras,+rcpc,+rdm,+sb,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a710" "target-features"="+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+ete,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+ssbs,+sve,+sve2,+sve2-bitperm,+trbe,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a" } // CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="cortex-a710" } // CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+ete,+fp-armv8,+neon,+trbe,+v8a" } // CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } // CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+v8.1a,+v8.2a,+v8a" "tune-cpu"="cortex-a710" } // CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" } -// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" } +// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" } +// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" } // CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" } // CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16" } -// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "branch-target-enforcement" "guarded-control-stack" "no-trapping-math"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "branch-target-enforcement" "guarded-control-stack" "no-trapping-math"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } // CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } // CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.3a" } //. diff --git a/clang/test/CodeGen/bit-int-ubsan.c b/clang/test/CodeGen/bit-int-ubsan.c new file mode 100644 index 000000000000000..40e4fde1d1f417f --- /dev/null +++ b/clang/test/CodeGen/bit-int-ubsan.c @@ -0,0 +1,78 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -emit-llvm -o - %s | FileCheck %s + +// The runtime test checking the _BitInt ubsan feature is located in compiler-rt/test/ubsan/TestCases/Integer/bit-int.c + +typedef unsigned int uint32_t; +uint32_t float_divide_by_zero() { + float f = 1.0f / 0.0f; + // CHECK: constant { i16, i16, [8 x i8] } { i16 1, i16 32, [8 x i8] c"'float'\00" } + _BitInt(37) r = (_BitInt(37))f; + // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(37)'\00%\00\00\00\00\00" } + return r; +} + +uint32_t integer_divide_by_zero() __attribute__((no_sanitize("memory"))) { + _BitInt(37) x = 1 / 0; + // CHECK: constant { i16, i16, [32 x i8] } { i16 0, i16 10, [32 x i8] c"'uint32_t' (aka 'unsigned int')\00" } + return x; +} + +uint32_t implicit_unsigned_integer_truncation() { + unsigned _BitInt(37) x = 2U; + x += float_divide_by_zero(); + x += integer_divide_by_zero(); + x = x + 0xFFFFFFFFFFFFFFFFULL; + // CHECK: constant { i16, i16, [23 x i8] } { i16 0, i16 12, [23 x i8] c"'unsigned _BitInt(37)'\00" } + uint32_t r = x & 0xFFFFFFFF; + return r; +} + +uint32_t array_bounds() { + _BitInt(37) x[4]; + _BitInt(37) y = x[10]; + // CHECK: constant { i16, i16, [17 x i8] } { i16 -1, i16 0, [17 x i8] c"'_BitInt(37)[4]'\00" } + return (uint32_t)y; +} + +uint32_t float_cast_overflow() { + float a = 100000000.0f; + _BitInt(7) b = (_BitInt(7))a; + // CHECK: constant { i16, i16, [19 x i8] } { i16 2, i16 7, [19 x i8] c"'_BitInt(7)'\00\07\00\00\00\00\00" } + return b; +} + +_BitInt(13) implicit_signed_integer_truncation() { + _BitInt(73) x = (_BitInt(73)) ~((~0UL) >> 1); + return x; + // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 {{([[:xdigit:]]{2})}}, [20 x i8] c"'_BitInt(73)'\00I\00\00\00\00\00" } + // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 9, [20 x i8] c"'_BitInt(13)'\00\0D\00\00\00\00\00" } +} + +uint32_t negative_shift1(unsigned _BitInt(37) x) + __attribute__((no_sanitize("memory"))) { + _BitInt(9) c = -2; + return x >> c; + // CHECK: constant { i16, i16, [19 x i8] } { i16 2, i16 9, [19 x i8] c"'_BitInt(9)'\00\09\00\00\00\00\00" } +} + +uint32_t negative_shift2(unsigned _BitInt(37) x) + __attribute__((no_sanitize("memory"))) { + _BitInt(17) c = -2; + return x >> c; + // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 11, [20 x i8] c"'_BitInt(17)'\00\11\00\00\00\00\00" } +} + +uint32_t negative_shift3(unsigned _BitInt(37) x) + __attribute__((no_sanitize("memory"))) { + _BitInt(34) c = -2; + return x >> c; + // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(34)'\00\22\00\00\00\00\00" } +} + +uint32_t negative_shift5(unsigned _BitInt(37) x) + __attribute__((no_sanitize("memory"))) { + _BitInt(68) c = -2; + return x >> c; + // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 {{([[:xdigit:]]{2})}}, [20 x i8] c"'_BitInt(68)'\00D\00\00\00\00\00" } +} diff --git a/clang/test/CodeGen/builtins-nvptx.c b/clang/test/CodeGen/builtins-nvptx.c index 75b9d6d1fe1902c..20399b73e637575 100644 --- a/clang/test/CodeGen/builtins-nvptx.c +++ b/clang/test/CodeGen/builtins-nvptx.c @@ -22,6 +22,9 @@ // RUN: %clang_cc1 -ffp-contract=off -triple nvptx64-unknown-unknown -target-cpu sm_86 -target-feature +ptx72 \ // RUN: -fcuda-is-device -emit-llvm -o - -x cuda %s \ // RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK_PTX72_SM86 -check-prefix=LP64 %s +// RUN: %clang_cc1 -ffp-contract=off -triple nvptx64-unknown-unknown -target-cpu sm_89 -target-feature +ptx81 \ +// RUN: -fcuda-is-device -emit-llvm -o - -x cuda %s \ +// RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK_PTX81_SM89 %s #define __device__ __attribute__((device)) #define __global__ __attribute__((global)) @@ -968,6 +971,39 @@ __device__ void nvvm_cvt_sm80() { // CHECK: ret void } +// CHECK-LABEL: nvvm_cvt_sm89 +__device__ void nvvm_cvt_sm89() { +#if __CUDA_ARCH__ >= 890 + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.ff.to.e4m3x2.rn(float 1.000000e+00, float 1.000000e+00) + __nvvm_ff_to_e4m3x2_rn(1.0f, 1.0f); + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.ff.to.e4m3x2.rn.relu(float 1.000000e+00, float 1.000000e+00) + __nvvm_ff_to_e4m3x2_rn_relu(1.0f, 1.0f); + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.ff.to.e5m2x2.rn(float 1.000000e+00, float 1.000000e+00) + __nvvm_ff_to_e5m2x2_rn(1.0f, 1.0f); + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.ff.to.e5m2x2.rn.relu(float 1.000000e+00, float 1.000000e+00) + __nvvm_ff_to_e5m2x2_rn_relu(1.0f, 1.0f); + + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.f16x2.to.e4m3x2.rn(<2 x half> ) + __nvvm_f16x2_to_e4m3x2_rn({1.0f16, 1.0f16}); + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.f16x2.to.e4m3x2.rn.relu(<2 x half> ) + __nvvm_f16x2_to_e4m3x2_rn_relu({1.0f16, 1.0f16}); + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.f16x2.to.e5m2x2.rn(<2 x half> ) + __nvvm_f16x2_to_e5m2x2_rn({1.0f16, 1.0f16}); + // CHECK_PTX81_SM89: call i16 @llvm.nvvm.f16x2.to.e5m2x2.rn.relu(<2 x half> ) + __nvvm_f16x2_to_e5m2x2_rn_relu({1.0f16, 1.0f16}); + + // CHECK_PTX81_SM89: call <2 x half> @llvm.nvvm.e4m3x2.to.f16x2.rn(i16 18504) + __nvvm_e4m3x2_to_f16x2_rn(0x4848); + // CHECK_PTX81_SM89: call <2 x half> @llvm.nvvm.e4m3x2.to.f16x2.rn.relu(i16 18504) + __nvvm_e4m3x2_to_f16x2_rn_relu(0x4848); + // CHECK_PTX81_SM89: call <2 x half> @llvm.nvvm.e5m2x2.to.f16x2.rn(i16 19532) + __nvvm_e5m2x2_to_f16x2_rn(0x4c4c); + // CHECK_PTX81_SM89: call <2 x half> @llvm.nvvm.e5m2x2.to.f16x2.rn.relu(i16 19532) + __nvvm_e5m2x2_to_f16x2_rn_relu(0x4c4c); +#endif + // CHECK: ret void +} + #define NAN32 0x7FBFFFFF #define NAN16 (__bf16)0x7FBF #define BF16 (__bf16)0.1f diff --git a/clang/test/CodeGen/overflow-idiom-exclusion-fp.c b/clang/test/CodeGen/overflow-idiom-exclusion-fp.c deleted file mode 100644 index 511a88cc7a28368..000000000000000 --- a/clang/test/CodeGen/overflow-idiom-exclusion-fp.c +++ /dev/null @@ -1,83 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-overflow-pattern-exclusion=all -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-overflow-pattern-exclusion=all -fwrapv -emit-llvm -o - %s | FileCheck %s - -// Check for potential false positives from patterns that _almost_ match classic overflow-dependent or overflow-prone code patterns -extern unsigned a, b, c; -extern int u, v, w; - -extern unsigned some(void); - -// Make sure all these still have handler paths, we shouldn't be excluding -// instrumentation of any "near" patterns. -// CHECK-LABEL: close_but_not_quite -void close_but_not_quite(void) { - // CHECK: br i1{{.*}}handler. - if (a + b > a) - c = 9; - - // CHECK: br i1{{.*}}handler. - if (a - b < a) - c = 9; - - // CHECK: br i1{{.*}}handler. - if (a + b < a) - c = 9; - - // CHECK: br i1{{.*}}handler. - if (a + b + 1 < a) - c = 9; - - // CHECK: br i1{{.*}}handler. - // CHECK: br i1{{.*}}handler. - if (a + b < a + 1) - c = 9; - - // CHECK: br i1{{.*}}handler. - if (b >= a + b) - c = 9; - - // CHECK: br i1{{.*}}handler. - if (a + a < a) - c = 9; - - // CHECK: br i1{{.*}}handler. - if (a + b == a) - c = 9; - - // CHECK: br i1{{.*}}handler - // Although this can never actually overflow we are still checking that the - // sanitizer instruments it. - while (--a) - some(); -} - -// cvise'd kernel code that caused problems during development -typedef unsigned _size_t; -typedef enum { FSE_repeat_none } FSE_repeat; -typedef enum { ZSTD_defaultAllowed } ZSTD_defaultPolicy_e; -FSE_repeat ZSTD_selectEncodingType_repeatMode; -ZSTD_defaultPolicy_e ZSTD_selectEncodingType_isDefaultAllowed; -_size_t ZSTD_NCountCost(void); - -// CHECK-LABEL: ZSTD_selectEncodingType -// CHECK: br i1{{.*}}handler -void ZSTD_selectEncodingType(void) { - _size_t basicCost = - ZSTD_selectEncodingType_isDefaultAllowed ? ZSTD_NCountCost() : 0, - compressedCost = 3 + ZSTD_NCountCost(); - if (basicCost <= compressedCost) - ZSTD_selectEncodingType_repeatMode = FSE_repeat_none; -} - -// CHECK-LABEL: function_calls -void function_calls(void) { - // CHECK: br i1{{.*}}handler - if (some() + b < some()) - c = 9; -} - -// CHECK-LABEL: not_quite_a_negated_unsigned_const -void not_quite_a_negated_unsigned_const(void) { - // CHECK: br i1{{.*}}handler - a = -b; -} diff --git a/clang/test/CodeGen/sanitize-ignorelist-mainfile.c b/clang/test/CodeGen/sanitize-ignorelist-mainfile.c index 84d58b4c018e3a2..419e0417c1d8296 100644 --- a/clang/test/CodeGen/sanitize-ignorelist-mainfile.c +++ b/clang/test/CodeGen/sanitize-ignorelist-mainfile.c @@ -1,8 +1,8 @@ /// Test mainfile in a sanitizer special case list. -// RUN: rm -rf %t && split-file %s %t && cd %t -// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=address,alignment a.c -o - | FileCheck %s --check-prefixes=CHECK,DEFAULT -// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=address,alignment -fsanitize-ignorelist=a.list a.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE -// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=address,alignment -fsanitize-ignorelist=b.list a.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE +// RUN: rm -rf %t && split-file %s %t +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=address,alignment %t/a.c -o - | FileCheck %s --check-prefixes=CHECK,DEFAULT +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=address,alignment -fsanitize-ignorelist=%t/a.list %t/a.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=address,alignment -fsanitize-ignorelist=%t/b.list %t/a.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE //--- a.list mainfile:*a.c diff --git a/clang/test/CodeGenCXX/amdgpu-kernel-arg-pointer-type.cpp b/clang/test/CodeGenCXX/amdgpu-kernel-arg-pointer-type.cpp index c8fb12315d0eeca..8df1d75e9ec8fa4 100644 --- a/clang/test/CodeGenCXX/amdgpu-kernel-arg-pointer-type.cpp +++ b/clang/test/CodeGenCXX/amdgpu-kernel-arg-pointer-type.cpp @@ -6,6 +6,10 @@ // The original test passes the result through opt O2, but that seems to introduce invalid // addrspace casts which are not being fixed as part of the present change. +// COMMON: define{{.*}} amdgpu_kernel void @_Z6kernelv() #[[ATTR:[0-9]+]] +__attribute__((amdgpu_kernel, amdgpu_flat_work_group_size(1, 256))) void + kernel() {} + // COMMON-LABEL: define{{.*}} amdgpu_kernel void @_Z7kernel1Pi(ptr {{.*}} %x) // CHECK-NOT: ={{.*}} addrspacecast [[TYPE:.*]] addrspace(1)* %{{.*}} to ptr __attribute__((amdgpu_kernel)) void kernel1(int *x) { @@ -81,3 +85,4 @@ __attribute__((amdgpu_kernel)) void kernel8(struct SS a) { *a.x += 3.f; } +// COMMON: attributes #[[ATTR]] = { {{.*}}"amdgpu-flat-work-group-size"="1,256"{{.*}} } diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp deleted file mode 100644 index 737c9c407f47037..000000000000000 --- a/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.20 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck %s - -struct StructA {}; - -template -auto AutoT() { return T(); } - -template -const auto AutoConstT() { return T(); } - -template -volatile auto AutoVolatileT() { return T(); } - -template -const volatile auto AutoConstVolatileT() { return T(); } - -// The qualifiers of the return type should always be emitted even for void types. -// Void types usually have their qualifers stripped in the mangled name for MSVC ABI. -void test_template_auto_void() { - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@X@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CBX@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CCX@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CDX@@YA?A_PXZ" - - AutoConstT(); - // CHECK: call {{.*}} @"??$AutoConstT@X@@YA?B_PXZ" - - AutoVolatileT(); - // CHECK: call {{.*}} @"??$AutoVolatileT@X@@YA?C_PXZ" - - AutoConstVolatileT(); - // CHECK: call {{.*}} @"??$AutoConstVolatileT@X@@YA?D_PXZ" -} - -void test_template_auto_int() { - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@H@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CBH@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CCH@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CDH@@YA?A_PXZ" - - AutoConstT(); - // CHECK: call {{.*}} @"??$AutoConstT@H@@YA?B_PXZ" - - AutoVolatileT(); - // CHECK: call {{.*}} @"??$AutoVolatileT@H@@YA?C_PXZ" - - AutoConstVolatileT(); - // CHECK: call {{.*}} @"??$AutoConstVolatileT@H@@YA?D_PXZ" -} - -void test_template_auto_struct() { - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@UStructA@@@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ" - - AutoConstT(); - // CHECK: call {{.*}} @"??$AutoConstT@UStructA@@@@YA?B_PXZ" - - AutoVolatileT(); - // CHECK: call {{.*}} @"??$AutoVolatileT@UStructA@@@@YA?C_PXZ" - - AutoConstVolatileT(); - // CHECK: call {{.*}} @"??$AutoConstVolatileT@UStructA@@@@YA?D_PXZ" -} - -void test_template_auto_ptr() { - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@PEAH@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@PEBH@@YA?A_PXZ" - - AutoT(); - // CHECK: call {{.*}} @"??$AutoT@QEBH@@YA?A_PXZ" - - AutoConstT(); - // CHECK: call {{.*}} @"??$AutoConstT@PEAH@@YA?B_PXZ" - - AutoVolatileT(); - // CHECK: call {{.*}} @"??$AutoVolatileT@PEAH@@YA?C_PXZ" - - AutoConstVolatileT(); - // CHECK: call {{.*}} @"??$AutoConstVolatileT@PEAH@@YA?D_PXZ" -} - -template -auto* PtrAutoT() { return T(); } - -template -const auto* PtrAutoConstT() { return T(); } - -template -volatile auto* PtrAutoVolatileT() { return T(); } - -template -const volatile auto* PtrAutoConstVolatileT() { return T(); } - -void test_template_ptr_auto() { - PtrAutoT(); - // CHECK: call {{.*}} @"??$PtrAutoT@PEAH@@YAPEA_PXZ" - - PtrAutoT(); - // CHECK: call {{.*}} @"??$PtrAutoT@PEBH@@YAPEA_PXZ" - - PtrAutoT(); - // CHECK: call {{.*}} @"??$PtrAutoT@QEBH@@YAPEA_PXZ" - - PtrAutoConstT(); - // CHECK: call {{.*}} @"??$PtrAutoConstT@PEAH@@YAPEB_PXZ" - - PtrAutoVolatileT(); - // CHECK: call {{.*}} @"??$PtrAutoVolatileT@PEAH@@YAPEC_PXZ" - - PtrAutoConstVolatileT(); - // CHECK: call {{.*}} @"??$PtrAutoConstVolatileT@PEAH@@YAPED_PXZ" -} - -int func_int(); -const int func_constint(); -void func_void(); -int* func_intptr(); - -template -auto (*FuncPtrAutoT())() { return v; } - -void test_template_func_ptr_auto() { - FuncPtrAutoT(); - // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ" - - FuncPtrAutoT(); - // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ" - - FuncPtrAutoT(); - // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ" - - FuncPtrAutoT(); - // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6APEAHXZ$1?func_intptr@@YAPEAHXZ@@YAP6A?A_PXZXZ" -} - -template -auto& RefAutoT(T& x) { return x; } - -template -const auto& ConstRefAutoT(T& x) { return x; } - -template -auto&& RRefAutoT(T& x) { return static_cast(x); } - -void test_template_ref_auto() { - int x; - - RefAutoT(x); - // CHECK: call {{.*}} @"??$RefAutoT@H@@YAAEA_PAEAH@Z" - - ConstRefAutoT(x); - // CHECK: call {{.*}} @"??$ConstRefAutoT@H@@YAAEB_PAEAH@Z" - - RRefAutoT(x); - // CHECK: call {{.*}} @"??$RRefAutoT@H@@YA$$QEA_PAEAH@Z" -} - -template -decltype(auto) DecltypeAutoT() { return T(); } - -template -decltype(auto) DecltypeAutoT2(T& x) { return static_cast(x); } - -void test_template_decltypeauto() { - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@X@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBX@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCX@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDX@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@H@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBH@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCH@@YA?A_TXZ" - - DecltypeAutoT(); - // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDH@@YA?A_TXZ" - - int x; - - DecltypeAutoT2(x); - // CHECK: call {{.*}} @"??$DecltypeAutoT2@H@@YA?A_TAEAH@Z" -} - -// Still want to use clang's custom mangling for lambdas to keep backwards compatibility until -// MSVC lambda name mangling has been deciphered. -void test_lambda() { - auto lambdaIntRetAuto = []() { return 0; }; - lambdaIntRetAuto(); - // CHECK: call {{.*}} @"??R@?0??test_lambda@@YAXXZ@QEBA?A?@@XZ" - - auto lambdaIntRet = []() -> int { return 0; }; - lambdaIntRet(); - // CHECK: call {{.*}} @"??R@?0??test_lambda@@YAXXZ@QEBA@XZ" - - auto lambdaGenericIntIntRetAuto = [](auto a) { return a; }; - lambdaGenericIntIntRetAuto(0); - // CHECK: call {{.*}} @"??$?RH@@?0??test_lambda@@YAXXZ@QEBA?A?@@H@Z" -} - -auto TestTrailingInt() -> int { - return 0; -} - -auto TestTrailingConstVolatileVoid() -> const volatile void { -} - -auto TestTrailingStructA() -> StructA { - return StructA{}; -} - -void test_trailing_return() { - TestTrailingInt(); - // CHECK: call {{.*}} @"?TestTrailingInt@@YAHXZ" - - TestTrailingConstVolatileVoid(); - // CHECK: call {{.*}} @"?TestTrailingConstVolatileVoid@@YAXXZ" - - TestTrailingStructA(); - // CHECK: call {{.*}} @"?TestTrailingStructA@@YA?AUStructA@@XZ" -} - -auto TestNonTemplateAutoInt() { - return 0; -} - -auto TestNonTemplateAutoVoid() { - return; -} - -auto TestNonTemplateAutoStructA() { - return StructA{}; -} - -const auto TestNonTemplateConstAutoInt() { - return 0; -} - -const auto TestNonTemplateConstAutoVoid() { - return; -} - -const auto TestNonTemplateConstAutoStructA() { - return StructA{}; -} - -void test_nontemplate_auto() { - TestNonTemplateAutoInt(); - // CHECK: call {{.*}} @"?TestNonTemplateAutoInt@@YA@XZ" - - TestNonTemplateAutoVoid(); - // CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA@XZ" - - TestNonTemplateAutoStructA(); - // CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA@XZ" - - TestNonTemplateConstAutoInt(); - // CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA@XZ" - - TestNonTemplateConstAutoVoid(); - // CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA@XZ" - - TestNonTemplateConstAutoStructA(); - // CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA@XZ" -} - -decltype(auto) TestNonTemplateDecltypeAutoInt() { - return 0; -} - -decltype(auto) TestNonTemplateDecltypeAutoVoid() { - return; -} - -decltype(auto) TestNonTemplateDecltypeAutoStructA() { - return StructA{}; -} - -void test_nontemplate_decltypeauto() { - TestNonTemplateDecltypeAutoInt(); - // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA@XZ" - - TestNonTemplateDecltypeAutoVoid(); - // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA@XZ" - - TestNonTemplateDecltypeAutoStructA(); - // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA@XZ" -} - -struct StructB { - int x; -}; - -template -auto StructB::* AutoMemberDataPtrT(T x) { return x; } - -template -const auto StructB::* AutoConstMemberDataPtrT(T x) { return x; } - -void test_template_auto_member_data_ptr() { - AutoMemberDataPtrT(&StructB::x); - // CHECK: call {{.*}} @"??$AutoMemberDataPtrT@PEQStructB@@H@@YAPEQStructB@@_PPEQ0@H@Z" - - AutoConstMemberDataPtrT(&StructB::x); - // CHECK: call {{.*}} @"??$AutoConstMemberDataPtrT@PEQStructB@@H@@YAPERStructB@@_PPEQ0@H@Z" -} - -struct StructC { - void test() {} -}; - -struct StructD { - const int test() { return 0; } -}; - -template -auto (StructC::*AutoMemberFuncPtrT(T x))() { return x; } - -template -const auto (StructD::*AutoConstMemberFuncPtrT(T x))() { return x; } - -void test_template_auto_member_func_ptr() { - AutoMemberFuncPtrT(&StructC::test); - // CHECK: call {{.*}} @"??$AutoMemberFuncPtrT@P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80@EAAXXZ@Z" - - AutoConstMemberFuncPtrT(&StructD::test); - // CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT@P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80@EAA?BHXZ@Z" -} - -template -auto * __attribute__((address_space(1))) * AutoPtrAddressSpaceT() { - T * __attribute__((address_space(1))) * p = nullptr; - return p; -} - -void test_template_auto_address_space_ptr() { - AutoPtrAddressSpaceT(); - // CHECK: call {{.*}} @"??$AutoPtrAddressSpaceT@H@@YA?A?@@XZ" -} diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp index b7bc3953f0b4380..360ebdecc5562be 100644 --- a/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp @@ -34,15 +34,15 @@ void template_mangling() { // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$I?f@V@@QEAAXXZA@A@@@QEAA@XZ" AutoFunc<&S::f>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MP8S@@EAAXXZ1?f@1@QEAAXXZ@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MP8S@@EAAXXZ1?f@1@QEAAXXZ@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$1?f@S@@QEAAXXZ@@YA?A?@@XZ" AutoFunc<&M::f>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MP8M@@EAAXXZH?f@1@QEAAXXZA@@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MP8M@@EAAXXZH?f@1@QEAAXXZA@@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$H?f@M@@QEAAXXZA@@@YA?A?@@XZ" AutoFunc<&V::f>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MP8V@@EAAXXZI?f@1@QEAAXXZA@A@@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MP8V@@EAAXXZI?f@1@QEAAXXZA@A@@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$I?f@V@@QEAAXXZA@A@@@YA?A?@@XZ" AutoParmTemplate<&S::a> auto_data_single_inheritance; @@ -58,14 +58,14 @@ void template_mangling() { // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$FBA@A@@@QEAA@XZ" AutoFunc<&S::a>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MPEQS@@H07@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MPEQS@@H07@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$07@@YA?A?@@XZ" AutoFunc<&M::a>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MPEQM@@H0M@@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MPEQM@@H0M@@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$0M@@@YA?A?@@XZ" AutoFunc<&V::a>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MPEQV@@HFBA@A@@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MPEQV@@HFBA@A@@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$FBA@A@@@YA?A?@@XZ" } diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp index 251d9219c01ce28..8f98c1e59f73d79 100644 --- a/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp @@ -19,6 +19,6 @@ void template_mangling() { // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0A@@@QEAA@XZ" AutoFunc(); - // AFTER: call {{.*}} @"??$AutoFunc@$M$$T0A@@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$M$$T0A@@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$0A@@@YA?A?@@XZ" } diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp index effcc31ee311038..ff5395cea75eb77 100644 --- a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp @@ -26,7 +26,7 @@ int j; void template_mangling() { AutoFunc<1>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MH00@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MH00@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$00@@YA?A?@@XZ" AutoParmTemplate<0> auto_int; // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MH0A@@@QEAA@XZ" @@ -52,7 +52,7 @@ void template_mangling() { // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$00$0HPPPPPPPPPPPPPPP@@@QEAA@XZ" AutoFunc<&i>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MPEAH1?i@@3HA@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MPEAH1?i@@3HA@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$1?i@@3HA@@YA?A?@@XZ" AutoParmTemplate<&i> auto_int_ptr; @@ -64,7 +64,7 @@ void template_mangling() { // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$1?i@@3HA$1?j@@3HA@@QEAA@XZ" AutoFunc<&Func>(); - // AFTER: call {{.*}} @"??$AutoFunc@$MP6AHXZ1?Func@@YAHXZ@@YA?A_PXZ" + // AFTER: call {{.*}} @"??$AutoFunc@$MP6AHXZ1?Func@@YAHXZ@@YA?A?@@XZ" // BEFORE: call {{.*}} @"??$AutoFunc@$1?Func@@YAHXZ@@YA?A?@@XZ" AutoParmTemplate<&Func> auto_func_ptr; diff --git a/clang/test/CodeGenHLSL/default_validator_version.hlsl b/clang/test/CodeGenHLSL/default_validator_version.hlsl new file mode 100644 index 000000000000000..907526dd685a966 --- /dev/null +++ b/clang/test/CodeGenHLSL/default_validator_version.hlsl @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -xhlsl -o - %s | FileCheck %s + +// CHECK:!dx.valver = !{![[valver:[0-9]+]]} +// CHECK:![[valver]] = !{i32 1, i32 8} + +float bar(float a, float b); + +float foo(float a, float b) { + return bar(a, b); +} diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl index f44465746356878..138616ccca7182a 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl @@ -49,7 +49,7 @@ void test_s_wait_event_export_ready() { } // CHECK-LABEL: @test_global_add_f32 -// CHECK: {{.*}}call{{.*}} float @llvm.amdgcn.global.atomic.fadd.f32.p1.f32(ptr addrspace(1) %{{.*}}, float %{{.*}}) +// CHECK: = atomicrmw fadd ptr addrspace(1) %addr, float %x syncscope("agent") monotonic, align 4, !amdgpu.no.fine.grained.memory !{{[0-9]+}}, !amdgpu.ignore.denormal.mode !{{[0-9]+$}} void test_global_add_f32(float *rtn, global float *addr, float x) { *rtn = __builtin_amdgcn_global_atomic_fadd_f32(addr, x); } diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl index 63381942eaba574..6b8a6d14575db88 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl @@ -11,7 +11,7 @@ typedef short __attribute__((ext_vector_type(2))) short2; // CHECK-LABEL: test_local_add_2bf16 // CHECK: [[BC0:%.+]] = bitcast <2 x i16> {{.+}} to <2 x bfloat> -// CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x bfloat> [[BC0]] seq_cst, align 4 +// CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x bfloat> [[BC0]] syncscope("agent") monotonic, align 4 // CHECK-NEXT: bitcast <2 x bfloat> [[RMW]] to <2 x i16> // GFX12-LABEL: test_local_add_2bf16 @@ -22,7 +22,7 @@ short2 test_local_add_2bf16(__local short2 *addr, short2 x) { // CHECK-LABEL: test_local_add_2bf16_noret // CHECK: [[BC0:%.+]] = bitcast <2 x i16> {{.+}} to <2 x bfloat> -// CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x bfloat> [[BC0]] seq_cst, align 4 +// CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x bfloat> [[BC0]] syncscope("agent") monotonic, align 4 // CHECK-NEXT: bitcast <2 x bfloat> [[RMW]] to <2 x i16> // GFX12-LABEL: test_local_add_2bf16_noret @@ -32,7 +32,7 @@ void test_local_add_2bf16_noret(__local short2 *addr, short2 x) { } // CHECK-LABEL: test_local_add_2f16 -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} monotonic, align 4 // GFX12-LABEL: test_local_add_2f16 // GFX12: ds_pk_add_rtn_f16 half2 test_local_add_2f16(__local half2 *addr, half2 x) { @@ -40,7 +40,7 @@ half2 test_local_add_2f16(__local half2 *addr, half2 x) { } // CHECK-LABEL: test_local_add_2f16_noret -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} monotonic, align 4 // GFX12-LABEL: test_local_add_2f16_noret // GFX12: ds_pk_add_f16 void test_local_add_2f16_noret(__local half2 *addr, half2 x) { diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl index ad4d0b7af3d4be7..2f00977ec6014e1 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl @@ -6,7 +6,7 @@ // REQUIRES: amdgpu-registered-target // CHECK-LABEL: test_fadd_local -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, float %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, float %{{.+}} monotonic, align 4 // GFX8-LABEL: test_fadd_local$local: // GFX8: ds_add_rtn_f32 v2, v0, v1 // GFX8: s_endpgm @@ -16,7 +16,7 @@ kernel void test_fadd_local(__local float *ptr, float val){ } // CHECK-LABEL: test_fadd_local_volatile -// CHECK: = atomicrmw volatile fadd ptr addrspace(3) %{{.+}}, float %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw volatile fadd ptr addrspace(3) %{{.+}}, float %{{.+}} monotonic, align 4 kernel void test_fadd_local_volatile(volatile __local float *ptr, float val){ volatile float *res; *res = __builtin_amdgcn_ds_atomic_fadd_f32(ptr, val); diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl index e2117f11858f7f8..c525c250c937cad 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl @@ -9,7 +9,7 @@ typedef half __attribute__((ext_vector_type(2))) half2; // CHECK-LABEL: test_global_add_f64 -// CHECK: call double @llvm.amdgcn.global.atomic.fadd.f64.p1.f64(ptr addrspace(1) %{{.*}}, double %{{.*}}) +// CHECK: = atomicrmw fadd ptr addrspace(1) %{{.+}}, double %{{.+}} syncscope("agent") monotonic, align 8, !amdgpu.no.fine.grained.memory !{{[0-9]+$}} // GFX90A-LABEL: test_global_add_f64$local: // GFX90A: global_atomic_add_f64 void test_global_add_f64(__global double *addr, double x) { @@ -99,7 +99,7 @@ void test_flat_global_max_f64(__global double *addr, double x){ } // CHECK-LABEL: test_ds_add_local_f64 -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, double %{{.+}} seq_cst, align 8 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, double %{{.+}} monotonic, align 8 // GFX90A: test_ds_add_local_f64$local // GFX90A: ds_add_rtn_f64 void test_ds_add_local_f64(__local double *addr, double x){ @@ -108,7 +108,7 @@ void test_ds_add_local_f64(__local double *addr, double x){ } // CHECK-LABEL: test_ds_addf_local_f32 -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, float %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, float %{{.+}} monotonic, align 4 // GFX90A-LABEL: test_ds_addf_local_f32$local // GFX90A: ds_add_rtn_f32 void test_ds_addf_local_f32(__local float *addr, float x){ @@ -117,7 +117,7 @@ void test_ds_addf_local_f32(__local float *addr, float x){ } // CHECK-LABEL: @test_global_add_f32 -// CHECK: call float @llvm.amdgcn.global.atomic.fadd.f32.p1.f32(ptr addrspace(1) %{{.*}}, float %{{.*}}) +// CHECK: = atomicrmw fadd ptr addrspace(1) %{{.+}}, float %{{.+}} syncscope("agent") monotonic, align 4, !amdgpu.no.fine.grained.memory !{{[0-9]+}}, !amdgpu.ignore.denormal.mode !{{[0-9]+$}} void test_global_add_f32(float *rtn, global float *addr, float x) { *rtn = __builtin_amdgcn_global_atomic_fadd_f32(addr, x); } diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx940.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx940.cl index 92a33ceac2290f5..5481138b9fee43a 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx940.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx940.cl @@ -44,7 +44,7 @@ short2 test_global_add_2bf16(__global short2 *addr, short2 x) { // CHECK-LABEL: test_local_add_2bf16 // CHECK: [[BC0:%.+]] = bitcast <2 x i16> {{.+}} to <2 x bfloat> -// CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x bfloat> [[BC0]] seq_cst, align 4 +// CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x bfloat> [[BC0]] syncscope("agent") monotonic, align 4{{$}} // CHECK-NEXT: bitcast <2 x bfloat> [[RMW]] to <2 x i16> // GFX940-LABEL: test_local_add_2bf16 @@ -54,7 +54,7 @@ short2 test_local_add_2bf16(__local short2 *addr, short2 x) { } // CHECK-LABEL: test_local_add_2f16 -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} monotonic, align 4 // GFX940-LABEL: test_local_add_2f16 // GFX940: ds_pk_add_rtn_f16 half2 test_local_add_2f16(__local half2 *addr, half2 x) { @@ -62,7 +62,7 @@ half2 test_local_add_2f16(__local half2 *addr, half2 x) { } // CHECK-LABEL: test_local_add_2f16_noret -// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} seq_cst, align 4 +// CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, <2 x half> %{{.+}} monotonic, align 4 // GFX940-LABEL: test_local_add_2f16_noret // GFX940: ds_pk_add_f16 void test_local_add_2f16_noret(__local half2 *addr, half2 x) { @@ -70,7 +70,7 @@ void test_local_add_2f16_noret(__local half2 *addr, half2 x) { } // CHECK-LABEL: @test_global_add_f32 -// CHECK: call float @llvm.amdgcn.global.atomic.fadd.f32.p1.f32(ptr addrspace(1) %{{.*}}, float %{{.*}}) +// CHECK: = atomicrmw fadd ptr addrspace(1) %{{.+}}, float %{{.+}} syncscope("agent") monotonic, align 4, !amdgpu.no.fine.grained.memory !{{[0-9]+}}, !amdgpu.ignore.denormal.mode !{{[0-9]+$}} void test_global_add_f32(float *rtn, global float *addr, float x) { *rtn = __builtin_amdgcn_global_atomic_fadd_f32(addr, x); } diff --git a/clang/test/Driver/aarch64-negative-modifiers-for-default-features.c b/clang/test/Driver/aarch64-negative-modifiers-for-default-features.c new file mode 100644 index 000000000000000..03dd8af7588cae1 --- /dev/null +++ b/clang/test/Driver/aarch64-negative-modifiers-for-default-features.c @@ -0,0 +1,12 @@ +// Test that default features (e.g. flagm/sb/ssbs for 8.5) can be disabled via -march. + +// RUN: %clang --target=aarch64 -march=armv8.5-a+noflagm+nosb+nossbs -c %s -### 2>&1 | FileCheck %s +// CHECK: "-triple" "aarch64" +// CHECK-SAME: "-target-feature" "+v8.5a" +// CHECK-SAME: "-target-feature" "-flagm" +// CHECK-SAME: "-target-feature" "-sb" +// CHECK-SAME: "-target-feature" "-ssbs" + +// CHECK-NOT: "-target-feature" "+flagm" +// CHECK-NOT: "-target-feature" "+sb" +// CHECK-NOT: "-target-feature" "+ssbs" diff --git a/clang/test/Driver/arm-sb.c b/clang/test/Driver/arm-sb.c index f2704f33c271113..9c0f381171cb6df 100644 --- a/clang/test/Driver/arm-sb.c +++ b/clang/test/Driver/arm-sb.c @@ -11,6 +11,6 @@ // RUN: %clang -### -target arm-none-none-eabi %s 2>&1 | FileCheck %s --check-prefix=ABSENT // RUN: %clang -### -target aarch64-none-elf %s 2>&1 | FileCheck %s --check-prefix=ABSENT -// RUN: %clang -### -target aarch64-none-elf -march=armv8.5a+nosb %s 2>&1 | FileCheck %s --check-prefix=ABSENT +// RUN: %clang -### -target aarch64-none-elf -march=armv8.5a+nosb %s 2>&1 | FileCheck %s --check-prefix=NOSB // ABSENT-NOT: "-target-feature" "+sb" // ABSENT-NOT: "-target-feature" "-sb" diff --git a/clang/test/Driver/arm-target-as-mimplicit-it.s b/clang/test/Driver/arm-target-as-mimplicit-it.s index d30433ab374d598..e40206dfc3a2938 100644 --- a/clang/test/Driver/arm-target-as-mimplicit-it.s +++ b/clang/test/Driver/arm-target-as-mimplicit-it.s @@ -30,7 +30,7 @@ /// Test invalid input. // RUN: not %clang -target arm-linux-gnueabi -### -Wa,-mimplicit-it=foo %s 2>&1 | FileCheck %s --check-prefix=INVALID -// RUN: not %clang -target arm-linux-gnueabi -### -Xassembler -mimplicit-it=foo %s 2>&1 | FileCheck %s --check-prefix=XINVALID +// RUN: not %clang -target arm-linux-gnueabi -### -Xassembler -mimplicit-it=foo %s 2>&1 | FileCheck %s --check-prefix=INVALID // RUN: not %clang -target arm-linux-gnueabi -### -Wa,-mimplicit-it=always -Wa,-mimplicit-it=foo %s 2>&1 | FileCheck %s --check-prefix=INVALID // RUN: not %clang -target arm-linux-gnueabi -### -Wa,-mimplicit-it=always,-mimplicit-it=foo %s 2>&1 | FileCheck %s --check-prefix=INVALID @@ -47,5 +47,4 @@ // NEVER-NOT: "-arm-implicit-it={{.*}}" // ARM: "-mllvm" "-arm-implicit-it=arm" // THUMB: "-mllvm" "-arm-implicit-it=thumb" -// INVALID: error: unsupported argument '-mimplicit-it=foo' to option '-Wa,' -// XINVALID: error: unsupported argument '-mimplicit-it=foo' to option '-Xassembler' +// INVALID: error: unsupported argument 'foo' to option '-Wa,-mimplicit-it=' diff --git a/clang/test/Driver/crel.c b/clang/test/Driver/crel.c index a47e7ebfeedd88f..e1b3f58c6ea5b73 100644 --- a/clang/test/Driver/crel.c +++ b/clang/test/Driver/crel.c @@ -24,8 +24,10 @@ /// The --allow-experimental-crel error check doesn't apply to LTO. // RUN: %clang -### --target=x86_64-linux -Werror -flto -Wa,--crel %s 2>&1 | FileCheck %s --check-prefix=LTO +// RUN: %clang -### --target=x86_64-linux -Werror -flto -Wa,--crel -Wa,--no-crel %s 2>&1 | FileCheck %s --check-prefix=LTO-NO // LTO: "-plugin-opt=-crel" +// LTO-NO-NOT: "-plugin-opt=-crel" // RUN: touch %t.o // RUN: not %clang -### --target=mips64-linux-gnu -flto -Wa,--crel %t.o 2>&1 | FileCheck %s --check-prefix=ERR diff --git a/clang/test/Driver/darwin-print-target-triple.c b/clang/test/Driver/darwin-print-target-triple.c deleted file mode 100644 index 4f5fdfe9d0db340..000000000000000 --- a/clang/test/Driver/darwin-print-target-triple.c +++ /dev/null @@ -1,42 +0,0 @@ -// Test the output of -print-target-triple on Darwin. -// See https://github.com/llvm/llvm-project/issues/61762 - -// -// All platforms -// - -// RUN: %clang -print-target-triple \ -// RUN: --target=x86_64-apple-macos -mmacos-version-min=15 \ -// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-MACOS %s -// CHECK-CLANGRT-MACOS: x86_64-apple-macosx15.0.0 - -// RUN: %clang -print-target-triple \ -// RUN: --target=arm64-apple-ios -mios-version-min=9 \ -// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-IOS %s -// CHECK-CLANGRT-IOS: arm64-apple-ios9.0.0 - -// RUN: %clang -print-target-triple \ -// RUN: --target=arm64-apple-watchos -mwatchos-version-min=3 \ -// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-WATCHOS %s -// CHECK-CLANGRT-WATCHOS: arm64-apple-watchos3.0.0 - -// RUN: %clang -print-target-triple \ -// RUN: --target=armv7k-apple-watchos -mwatchos-version-min=3 \ -// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-WATCHOS-ARMV7K %s -// CHECK-CLANGRT-WATCHOS-ARMV7K: thumbv7-apple-watchos3.0.0 - -// RUN: %clang -print-target-triple \ -// RUN: --target=arm64-apple-tvos -mtvos-version-min=1\ -// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-TVOS %s -// CHECK-CLANGRT-TVOS: arm64-apple-tvos1.0.0 - -// RUN: %clang -print-target-triple \ -// RUN: --target=arm64-apple-driverkit \ -// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-DRIVERKIT %s -// CHECK-CLANGRT-DRIVERKIT: arm64-apple-driverkit19.0.0 diff --git a/clang/test/Driver/flags.c b/clang/test/Driver/flags.c index 16b760609c36dd3..7d2bef63fca3e17 100644 --- a/clang/test/Driver/flags.c +++ b/clang/test/Driver/flags.c @@ -33,3 +33,6 @@ // // RUN: %clang --target=riscv64 -### -S -mno-implicit-float %s 2>&1 | FileCheck -check-prefix=TEST11 %s // TEST11: "-no-implicit-float" +// +// RUN: %clang --target=ppc64le -### -S -mno-red-zone %s 2>&1 | FileCheck -check-prefix=TEST12 %s +// TEST12: "-disable-red-zone" diff --git a/clang/test/Driver/hip-toolchain-rdc.hip b/clang/test/Driver/hip-toolchain-rdc.hip index 7e6697a0e254f6c..ec79bf06afb92c2 100644 --- a/clang/test/Driver/hip-toolchain-rdc.hip +++ b/clang/test/Driver/hip-toolchain-rdc.hip @@ -20,6 +20,29 @@ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,MSVC %s +// Test fatbin symbol search for -l libraries. + +// RUN: touch librdctest.a rdctest2.bin +// RUN: %clang -### --target=x86_64-linux-gnu -v \ +// RUN: -fgpu-rdc -nogpuinc -nogpulib \ +// RUN: --no-offload-new-driver -L. -lrdctest -l:rdctest2.bin \ +// RUN: %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=LIB,LNX-LIB %s +// RUN: rm librdctest.a rdctest2.bin + +// RUN: touch rdctest.lib rdctest2.bin +// RUN: %clang -### --target=x86_64-pc-windows-msvc -v \ +// RUN: -fgpu-rdc -nogpuinc -nogpulib \ +// RUN: --no-offload-new-driver -L. -lrdctest -l:rdctest2.bin \ +// RUN: %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=LIB,MSVC-LIB %s +// RUN: rm rdctest.lib rdctest2.bin + +// LIB: HIP fatbin symbol search uses library path: . +// LIB: HIP fatbin symbol search found library: .{{/|\\}}rdctest2.bin +// LNX-LIB: HIP fatbin symbol search found library: .{{/|\\}}librdctest.a +// MSVC-LIB: HIP fatbin symbol search found library: .{{/|\\}}rdctest.lib + // check HIP fatbin and gpubin handle symbols and code object alignment in dumped llvm-mc input // CHECK: Found undefined HIP fatbin symbol: __hip_fatbin_[[ID1:[0-9a-f]+]] // CHECK: Found undefined HIP fatbin symbol: __hip_fatbin_[[ID2:[0-9a-f]+]] diff --git a/clang/test/Driver/msse2avx.c b/clang/test/Driver/msse2avx.c index a63ac9a6c866815..829b1b2b79360d4 100644 --- a/clang/test/Driver/msse2avx.c +++ b/clang/test/Driver/msse2avx.c @@ -1,7 +1,7 @@ -// RUN: %clang -### -c -target x86_64 -march=x86-64 -Xassembler -msse2avx %s 2>&1 | FileCheck %s -// RUN: %clang -### -c -target x86_64 -march=x86-64 -x assembler -Xassembler -msse2avx %s 2>&1 | FileCheck %s +// RUN: %clang -### -c --target=x86_64 -march=x86-64 -Wa,-msse2avx %s 2>&1 | FileCheck %s +// RUN: %clang -### -c --target=x86_64 -march=x86-64 -x assembler -Xassembler -msse2avx %s 2>&1 | FileCheck %s // CHECK: "-msse2avx" -// RUN: not %clang -### -c -target aarch64 -march=armv8a -msse2avx %s 2>&1 | FileCheck --check-prefix=ERR %s -// ERR: error: unsupported option '-msse2avx' for target 'aarch64' +// RUN: not %clang -### -c --target=aarch64 -march=armv8a -Wa,-msse2avx %s 2>&1 | FileCheck --check-prefix=ERR %s +// ERR: error: unsupported argument '-msse2avx' to option '-Wa,' diff --git a/clang/test/Driver/ohos.c b/clang/test/Driver/ohos.c index 8de4e6de57f7ff8..af8218fb232e601 100644 --- a/clang/test/Driver/ohos.c +++ b/clang/test/Driver/ohos.c @@ -7,7 +7,6 @@ // RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=ld -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-ARM-A7-SOFT %s // CHECK: {{.*}}clang{{.*}}" "-cc1" -// CHECK-NOT: "--mrelax-relocations" // CHECK-NOT: "-munwind-tables" // CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK: "-isysroot" "[[SYSROOT:[^"]+]]" diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a12.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a12.c index 27f066a3107086a..fcc8b674df33f44 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a12.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a12.c @@ -6,7 +6,6 @@ // CHECK-NEXT: Architecture Feature(s) Description // CHECK-NEXT: FEAT_AES, FEAT_PMULL Enable AES support // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence // CHECK-NEXT: FEAT_FCMA Enable Armv8.3-A Floating-point complex number support diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a13.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a13.c index 197b21025995106..dae95b1297e1451 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a13.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a13.c @@ -7,7 +7,6 @@ // CHECK-NEXT: FEAT_AES, FEAT_PMULL Enable AES support // CHECK-NEXT: FEAT_AMUv1 Enable Armv8.4-A Activity Monitors extension // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions // CHECK-NEXT: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a14.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a14.c index f1731ef034a0c1f..8ddcddede4110d9 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a14.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a14.c @@ -7,7 +7,6 @@ // CHECK-NEXT: FEAT_AES, FEAT_PMULL Enable AES support // CHECK-NEXT: FEAT_AMUv1 Enable Armv8.4-A Activity Monitors extension // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a15.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a15.c index dec48bb70331141..b3f0acefd1e2d48 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a15.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a15.c @@ -10,7 +10,6 @@ // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions // CHECK-NEXT: FEAT_BF16 Enable BFloat16 Extension // CHECK-NEXT: FEAT_BTI Enable Branch Target Identification -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a16.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a16.c index 477652d83d82cbb..6f417c1592b06cd 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a16.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a16.c @@ -10,7 +10,6 @@ // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions // CHECK-NEXT: FEAT_BF16 Enable BFloat16 Extension // CHECK-NEXT: FEAT_BTI Enable Branch Target Identification -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a17.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a17.c index 311cc94acddc96e..39e5b70c25d8860 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-a17.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-a17.c @@ -10,7 +10,6 @@ // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions // CHECK-NEXT: FEAT_BF16 Enable BFloat16 Extension // CHECK-NEXT: FEAT_BTI Enable Branch Target Identification -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-apple-m4.c b/clang/test/Driver/print-enabled-extensions/aarch64-apple-m4.c index 44d618afef40689..29d66dc8826a77f 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-apple-m4.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-apple-m4.c @@ -10,7 +10,6 @@ // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions // CHECK-NEXT: FEAT_BF16 Enable BFloat16 Extension // CHECK-NEXT: FEAT_BTI Enable Branch Target Identification -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions @@ -52,7 +51,6 @@ // CHECK-NEXT: FEAT_SME_F64F64 Enable Scalable Matrix Extension (SME) F64F64 instructions // CHECK-NEXT: FEAT_SME_I16I64 Enable Scalable Matrix Extension (SME) I16I64 instructions // CHECK-NEXT: FEAT_SPECRES Enable Armv8.5-A execution and data prediction invalidation instructions -// CHECK-NEXT: FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit // CHECK-NEXT: FEAT_TLBIOS, FEAT_TLBIRANGE Enable Armv8.4-A TLB Range and Maintenance instructions // CHECK-NEXT: FEAT_TRF Enable Armv8.4-A Trace extension // CHECK-NEXT: FEAT_UAO Enable Armv8.2-A UAO PState diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82.c b/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82.c index 2b85201c2c6fe61..9875c6922d379a9 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82.c @@ -5,7 +5,6 @@ // CHECK-EMPTY: // CHECK-NEXT: Architecture Feature(s) Description // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82ae.c b/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82ae.c index 417687b4af287d4..2db44d7827aadb7 100644 --- a/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82ae.c +++ b/clang/test/Driver/print-enabled-extensions/aarch64-cortex-r82ae.c @@ -5,7 +5,6 @@ // CHECK-EMPTY: // CHECK-NEXT: Architecture Feature(s) Description // CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions -// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets // CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions // CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction // CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c index 9f58d1b557fd74d..2770a3ad5eaa1dd 100644 --- a/clang/test/Driver/print-multi-selection-flags.c +++ b/clang/test/Driver/print-multi-selection-flags.c @@ -58,3 +58,18 @@ // RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv9-a | FileCheck --check-prefix=CHECK-SVE2 %s // CHECK-SVE2: --target=aarch64-unknown-none-elf // CHECK-SVE2: -march=armv{{.*}}-a{{.*}}+simd{{.*}}+sve{{.*}}+sve2{{.*}} + +// RUN: %clang -print-multi-flags-experimental --target=riscv32-none-elf -march=rv32g | FileCheck --check-prefix=CHECK-RV32 %s +// CHECK-RV32: --target=riscv32-unknown-none-elf +// CHECK-RV32: -mabi=ilp32d +// CHECK-RV32: -march=rv32i{{[0-9]+p[0-9]+}}_m{{[0-9]+p[0-9]+}}_a{{[0-9]+p[0-9]+}}_f{{[0-9]+p[0-9]+}}_d{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}_zifencei{{[0-9]+p[0-9]+}}_zmmul{{[0-9]+p[0-9]+}} + +// RUN: %clang -print-multi-flags-experimental --target=riscv64-none-elf -march=rv64g | FileCheck --check-prefix=CHECK-RV64 %s +// CHECK-RV64: --target=riscv64-unknown-none-elf +// CHECK-RV64: -mabi=lp64d +// CHECK-RV64: -march=rv64i{{[0-9]+p[0-9]+}}_m{{[0-9]+p[0-9]+}}_a{{[0-9]+p[0-9]+}}_f{{[0-9]+p[0-9]+}}_d{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}_zifencei{{[0-9]+p[0-9]+}}_zmmul{{[0-9]+p[0-9]+}} + +// RUN: %clang -print-multi-flags-experimental --target=riscv32-none-elf -march=rv32e_zicsr_c | FileCheck --check-prefix=CHECK-RV32E-ORDER %s +// CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf +// CHECK-RV32E-ORDER: -mabi=ilp32e +// CHECK-RV32E-ORDER: -march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}} diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c index 91f12b8416b2a42..132422393170a90 100644 --- a/clang/test/Driver/print-supported-extensions-riscv.c +++ b/clang/test/Driver/print-supported-extensions-riscv.c @@ -172,6 +172,8 @@ // CHECK-NEXT: zicfiss 1.0 'Zicfiss' (Shadow stack) // CHECK-NEXT: zacas 1.0 'Zacas' (Atomic Compare-And-Swap Instructions) // CHECK-NEXT: zalasr 0.1 'Zalasr' (Load-Acquire and Store-Release Instructions) +// CHECK-NEXT: zvbc32e 0.7 'Zvbc32e' (Vector Carryless Multiplication with 32-bits elements) +// CHECK-NEXT: zvkgs 0.7 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography) // CHECK-NEXT: smmpm 1.0 'Smmpm' (Machine-level Pointer Masking for M-mode) // CHECK-NEXT: smnpm 1.0 'Smnpm' (Machine-level Pointer Masking for next lower privilege mode) // CHECK-NEXT: ssnpm 1.0 'Ssnpm' (Supervisor-level Pointer Masking for next lower privilege mode) diff --git a/clang/test/Driver/relax.c b/clang/test/Driver/relax.c index 48d22fede12d761..93249cac7f40f88 100644 --- a/clang/test/Driver/relax.c +++ b/clang/test/Driver/relax.c @@ -1,4 +1,13 @@ -// RUN: %clang -### -c -integrated-as -Wa,--mrelax-relocations=no %s 2>&1 | FileCheck %s +// RUN: %clang -### --target=x86_64 -c -Wa,--mrelax-relocations=no %s 2>&1 | FileCheck %s // CHECK: "-cc1" // CHECK: "-mrelax-relocations=no" + +// RUN: not %clang -### --target=x86_64 -c -Wa,-mrelax-relocations=x %s 2>&1 | FileCheck %s --check-prefix=ERR +// ERR: error: unsupported argument 'x' to option '-Wa,-mrelax-relocations=' + +// RUN: not %clang -### --target=aarch64 -c -Wa,-mrelax-relocations=no %s 2>&1 | FileCheck %s --check-prefix=ERR2 +// ERR2: error: unsupported argument '-mrelax-relocations=no' to option '-Wa,' + +// RUN: not %clang -### --target=x86_64-apple-darwin -c -Wa,-mrelax-relocations=no %s 2>&1 | FileCheck %s --check-prefix=ERR3 +// ERR3: error: unsupported option '-Wa,-mrelax-relocations=' for target 'x86_64-apple-darwin' diff --git a/clang/test/Driver/riscv-sdata-warning.c b/clang/test/Driver/riscv-sdata-warning.c deleted file mode 100644 index ace9a32ee116fd8..000000000000000 --- a/clang/test/Driver/riscv-sdata-warning.c +++ /dev/null @@ -1,4 +0,0 @@ -// REQUIRES: riscv-registered-target -// RUN: %clang -S --target=riscv32-unknown-elf -fpic -msmall-data-limit=8 %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-PIC-SDATA %s -// CHECK-PIC-SDATA: warning: ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64 diff --git a/clang/test/Driver/riscv-sdata.c b/clang/test/Driver/riscv-sdata.c new file mode 100644 index 000000000000000..84cd109813db4ca --- /dev/null +++ b/clang/test/Driver/riscv-sdata.c @@ -0,0 +1,5 @@ +// RUN: %clang -### -S --target=riscv64 %s 2>&1 | FileCheck %s +// RUN: %clang -### -S --target=riscv64 -msmall-data-limit=8 %s 2>&1 | FileCheck %s --check-prefix=EIGHT + +// CHECK-NOT: "-msmall-data-limit" +// EIGHT: "-msmall-data-limit" "8" diff --git a/clang/test/Driver/sparc-target-features.c b/clang/test/Driver/sparc-target-features.c index b36f63e7660e830..a839604ff1bc022 100644 --- a/clang/test/Driver/sparc-target-features.c +++ b/clang/test/Driver/sparc-target-features.c @@ -32,3 +32,6 @@ // RUN: %clang --target=sparc -msoft-quad-float %s -### 2>&1 | FileCheck -check-prefix=SOFT-QUAD-FLOAT %s // HARD-QUAD-FLOAT: "-target-feature" "+hard-quad-float" // SOFT-QUAD-FLOAT: "-target-feature" "-hard-quad-float" + +// RUN: %clang --target=sparc -mv8plus %s -### 2>&1 | FileCheck -check-prefix=V8PLUS %s +// V8PLUS: "-target-feature" "+v8plus" diff --git a/clang/test/ExtractAPI/inherited_availability.m b/clang/test/ExtractAPI/inherited_availability.m new file mode 100644 index 000000000000000..c24e7fa8e208f03 --- /dev/null +++ b/clang/test/ExtractAPI/inherited_availability.m @@ -0,0 +1,175 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing -triple arm64-apple-macosx \ +// RUN: -x objective-c-header %s -o %t/output.symbols.json -verify + + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix A +__attribute__((availability(macos, introduced=9.0, deprecated=12.0, obsoleted=20.0))) +@interface A +// A-LABEL: "!testLabel": "c:objc(cs)A" +// A: "availability": [ +// A-NEXT: { +// A-NEXT: "deprecated": { +// A-NEXT: "major": 12, +// A-NEXT: "minor": 0, +// A-NEXT: "patch": 0 +// A-NEXT: } +// A-NEXT: "domain": "macos" +// A-NEXT: "introduced": { +// A-NEXT: "major": 9, +// A-NEXT: "minor": 0, +// A-NEXT: "patch": 0 +// A-NEXT: } +// A-NEXT: "obsoleted": { +// A-NEXT: "major": 20, +// A-NEXT: "minor": 0, +// A-NEXT: "patch": 0 +// A-NEXT: } +// A-NEXT: } +// A-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix CP +@property(class) int CP; +// CP-LABEL: "!testLabel": "c:objc(cs)A(cpy)CP" +// CP: "availability": [ +// CP-NEXT: { +// CP-NEXT: "deprecated": { +// CP-NEXT: "major": 12, +// CP-NEXT: "minor": 0, +// CP-NEXT: "patch": 0 +// CP-NEXT: } +// CP-NEXT: "domain": "macos" +// CP-NEXT: "introduced": { +// CP-NEXT: "major": 9, +// CP-NEXT: "minor": 0, +// CP-NEXT: "patch": 0 +// CP-NEXT: } +// CP-NEXT: "obsoleted": { +// CP-NEXT: "major": 20, +// CP-NEXT: "minor": 0, +// CP-NEXT: "patch": 0 +// CP-NEXT: } +// CP-NEXT: } +// CP-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix IP +@property int IP; +// IP-LABEL: "!testLabel": "c:objc(cs)A(py)IP" +// IP: "availability": [ +// IP-NEXT: { +// IP-NEXT: "deprecated": { +// IP-NEXT: "major": 12, +// IP-NEXT: "minor": 0, +// IP-NEXT: "patch": 0 +// IP-NEXT: } +// IP-NEXT: "domain": "macos" +// IP-NEXT: "introduced": { +// IP-NEXT: "major": 9, +// IP-NEXT: "minor": 0, +// IP-NEXT: "patch": 0 +// IP-NEXT: } +// IP-NEXT: "obsoleted": { +// IP-NEXT: "major": 20, +// IP-NEXT: "minor": 0, +// IP-NEXT: "patch": 0 +// IP-NEXT: } +// IP-NEXT: } +// IP-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MR +@property int moreRestrictive __attribute__((availability(macos, introduced=10.0, deprecated=11.0, obsoleted=19.0))); +// MR-LABEL: "!testLabel": "c:objc(cs)A(py)moreRestrictive" +// MR: "availability": [ +// MR-NEXT: { +// MR-NEXT: "deprecated": { +// MR-NEXT: "major": 11, +// MR-NEXT: "minor": 0, +// MR-NEXT: "patch": 0 +// MR-NEXT: } +// MR-NEXT: "domain": "macos" +// MR-NEXT: "introduced": { +// MR-NEXT: "major": 10, +// MR-NEXT: "minor": 0, +// MR-NEXT: "patch": 0 +// MR-NEXT: } +// MR-NEXT: "obsoleted": { +// MR-NEXT: "major": 19, +// MR-NEXT: "minor": 0, +// MR-NEXT: "patch": 0 +// MR-NEXT: } +// MR-NEXT: } +// MR-NEXT: ] + +@end + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix B +__attribute__((deprecated("B is deprecated"))) +@interface B +// B-LABEL: "!testLabel": "c:objc(cs)B" +// B: "availability": [ +// B-NEXT: { +// B-NEXT: "domain": "*" +// B-NEXT: "isUnconditionallyDeprecated": true +// B-NEXT: } +// B-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BIP +@property int BIP; +// BIP-LABEL: "!testLabel": "c:objc(cs)B(py)BIP" +// BIP: "availability": [ +// BIP-NEXT: { +// BIP-NEXT: "domain": "*" +// BIP-NEXT: "isUnconditionallyDeprecated": true +// BIP-NEXT: } +// BIP-NEXT: ] +@end + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix C +__attribute__((availability(macos, unavailable))) +@interface C +// C-LABEL: "!testLabel": "c:objc(cs)C" +// C: "availability": [ +// C-NEXT: { +// C-NEXT: "domain": "macos" +// C-NEXT: "isUnconditionallyUnavailable": true +// C-NEXT: } +// C-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix CIP +@property int CIP; +// CIP-LABEL: "!testLabel": "c:objc(cs)C(py)CIP" +// CIP: "availability": [ +// CIP-NEXT: { +// CIP-NEXT: "domain": "macos" +// CIP-NEXT: "isUnconditionallyUnavailable": true +// CIP-NEXT: } +// CIP-NEXT: ] +@end + +@interface D +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix DIP +@property int DIP __attribute__((availability(macos, introduced=10.0, deprecated=11.0, obsoleted=19.0))); +// DIP-LABEL: "!testLabel": "c:objc(cs)D(py)DIP" +// DIP: "availability": [ +// DIP-NEXT: { +// DIP-NEXT: "deprecated": { +// DIP-NEXT: "major": 11, +// DIP-NEXT: "minor": 0, +// DIP-NEXT: "patch": 0 +// DIP-NEXT: } +// DIP-NEXT: "domain": "macos" +// DIP-NEXT: "introduced": { +// DIP-NEXT: "major": 10, +// DIP-NEXT: "minor": 0, +// DIP-NEXT: "patch": 0 +// DIP-NEXT: } +// DIP-NEXT: "obsoleted": { +// DIP-NEXT: "major": 19, +// DIP-NEXT: "minor": 0, +// DIP-NEXT: "patch": 0 +// DIP-NEXT: } +// DIP-NEXT: } +// DIP-NEXT: ] +@end + +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/platform-serialization.c b/clang/test/ExtractAPI/platform-serialization.c new file mode 100644 index 000000000000000..6d6a13f085cd9d9 --- /dev/null +++ b/clang/test/ExtractAPI/platform-serialization.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-ios17.1-macabi \ +// RUN: -x c-header %s -verify -o - | FileCheck %s + +int a; + +// CHECK: "platform": { +// CHECK-NEXT: "architecture": "arm64", +// CHECK-NEXT: "environment": "macabi", +// CHECK-NEXT: "operatingSystem": { +// CHECK-NEXT: "minimumVersion": { +// CHECK-NEXT: "major": 14, +// CHECK-NEXT: "minor": 0, +// CHECK-NEXT: "patch": 0 +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "ios" +// CHECK-NEXT: }, +// CHECK-NEXT: "vendor": "apple" +// CHECK-NEXT: } + +// expected-no-diagnostics diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp index 08b732132228bac..1c51013ca06f774 100644 --- a/clang/test/Lexer/cxx-features.cpp +++ b/clang/test/Lexer/cxx-features.cpp @@ -34,6 +34,10 @@ // --- C++26 features --- +#if check(variadic_friend, 202403, 202403, 202403, 202403, 202403, 202403, 202403) +#error "wrong value for __cpp_variadic_friend" +#endif + #if check(deleted_function, 202403, 202403, 202403, 202403, 202403, 202403, 202403) #error "wrong value for __cpp_deleted_function" #endif diff --git a/clang/test/Modules/enum-codegen.cpp b/clang/test/Modules/enum-codegen.cpp index 4397b457801da4e..0028ab00c15290f 100644 --- a/clang/test/Modules/enum-codegen.cpp +++ b/clang/test/Modules/enum-codegen.cpp @@ -1,5 +1,6 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fmodules-cache-path=%t %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fmodules-cache-path=%t %s -emit-llvm -o - -fexperimental-new-constant-interpreter | FileCheck %s // CHECK: @{{.*var.*}} = {{.*}} %union.union_type { i8 1 }, diff --git a/clang/test/Modules/merge-using-decls.cpp b/clang/test/Modules/merge-using-decls.cpp index e3bf977f0544993..e9794a40837ef97 100644 --- a/clang/test/Modules/merge-using-decls.cpp +++ b/clang/test/Modules/merge-using-decls.cpp @@ -6,7 +6,8 @@ // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify %s -DORDER=2 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++98 %s -DORDER=2 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++11 %s -DORDER=2 -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++17 %s -DORDER=2 + +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++17 %s -DORDER=2 #if ORDER == 1 #include "a.h" diff --git a/clang/test/OpenMP/loop_collapse_1.c b/clang/test/OpenMP/loop_collapse_1.c new file mode 100644 index 000000000000000..c9877419223dde4 --- /dev/null +++ b/clang/test/OpenMP/loop_collapse_1.c @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -verify %s + +void func( double *A, int N, int M, int NB ) { +#pragma omp parallel + { + int nblks = (N-1)/NB; + int lnb = ((N-1)/NB)*NB; + +#pragma omp for collapse(2) + for (int jblk = 0 ; jblk < nblks ; jblk++ ) { + int jb = (jblk == nblks - 1 ? lnb : NB); + for (int jk = 0; jk < N; jk+=jb) { // expected-error{{cannot use variable 'jb' in collapsed imperfectly-nested loop increment statement}} + } + } + +#pragma omp for collapse(2) + for (int a = 0; a < N; a++) { + for (int b = 0; b < M; b++) { + int cx = a+b < NB ? a : b; + for (int c = 0; c < cx; c++) { + } + } + } + +#pragma omp for collapse(3) + for (int a = 0; a < N; a++) { + for (int b = 0; b < M; b++) { + int cx = a+b < NB ? a : b; + for (int c = 0; c < cx; c++) { // expected-error{{cannot use variable 'cx' in collapsed imperfectly-nested loop condition statement}} + } + } + } + } +} + +int main(void) { + double arr[256]; + func (arr, 16, 16, 16); + return 0; +} diff --git a/clang/test/OpenMP/loop_collapse_2.cpp b/clang/test/OpenMP/loop_collapse_2.cpp new file mode 100644 index 000000000000000..59deddf65e37b54 --- /dev/null +++ b/clang/test/OpenMP/loop_collapse_2.cpp @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -verify %s + +// We just want to try out a range for statement... this seems a bit OTT. +template +class fakevector { + T *contents; + long size; +public: + fakevector(long sz) : size(sz) { + contents = new T[sz]; + } + ~fakevector() { + delete[] contents; + } + T& operator[](long x) { return contents[x]; } + typedef T *iterator; + fakevector::iterator begin() { + return &contents[0]; + } + fakevector::iterator end() { + return &contents[size]; + } +}; + +void func( double *A, int N, int M, int NB ) { +#pragma omp parallel + { + int nblks = (N-1)/NB; + int lnb = ((N-1)/NB)*NB; +#pragma omp for collapse(2) + for (int jblk = 0 ; jblk < nblks ; jblk++ ) { + int jb = (jblk == nblks - 1 ? lnb : NB); + for (int jk = 0; jk < N; jk+=jb) { // expected-error{{cannot use variable 'jb' in collapsed imperfectly-nested loop increment statement}} + } + } + +#pragma omp for collapse(2) + for (int a = 0; a < N; a++) { + for (int b = 0; b < M; b++) { + int cx = a+b < NB ? a : b; + for (int c = 0; c < cx; c++) { + } + } + } + + fakevector myvec{N}; +#pragma omp for collapse(2) + for (auto &a : myvec) { + fakevector myvec3{M}; + for (auto &b : myvec3) { // expected-error{{cannot use variable 'myvec3' in collapsed imperfectly-nested loop init statement}} + } + } + + fakevector myvec2{M}; + +#pragma omp for collapse(3) + for (auto &a : myvec) { + for (auto &b : myvec2) { + int cx = a < b ? N : M; + for (int c = 0; c < cx; c++) { // expected-error {{cannot use variable 'cx' in collapsed imperfectly-nested loop condition statement}} + } + } + } + +#pragma omp for collapse(3) + for (auto &a : myvec) { + int cx = a < 5 ? M : N; + for (auto &b : myvec2) { + for (int c = 0; c < cx; c++) { // expected-error{{cannot use variable 'cx' in collapsed imperfectly-nested loop condition statement}} + } + } + } + } +} + +int main(void) { + double arr[256]; + func (arr, 16, 16, 16); + return 0; +} diff --git a/clang/test/OpenMP/target_teams_codegen.cpp b/clang/test/OpenMP/target_teams_codegen.cpp index 9cab8eef1488330..13d44e127201bda 100644 --- a/clang/test/OpenMP/target_teams_codegen.cpp +++ b/clang/test/OpenMP/target_teams_codegen.cpp @@ -127,13 +127,13 @@ int foo(int n) { aa += 1; } - #pragma omp target teams ompx_bare num_teams(1, 2) thread_limit(1) + #pragma omp target teams ompx_bare num_teams(1, 2) thread_limit(1, 2) { a += 1; aa += 1; } - #pragma omp target teams ompx_bare num_teams(1, 2, 3) thread_limit(1) + #pragma omp target teams ompx_bare num_teams(1, 2, 3) thread_limit(1, 2, 3) { a += 1; aa += 1; @@ -667,7 +667,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP144:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 10 // CHECK1-NEXT: store [3 x i32] [i32 1, i32 2, i32 0], ptr [[TMP144]], align 4 // CHECK1-NEXT: [[TMP145:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 11 -// CHECK1-NEXT: store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP145]], align 4 +// CHECK1-NEXT: store [3 x i32] [i32 1, i32 2, i32 0], ptr [[TMP145]], align 4 // CHECK1-NEXT: [[TMP146:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 12 // CHECK1-NEXT: store i32 0, ptr [[TMP146]], align 4 // CHECK1-NEXT: [[TMP147:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 1, i32 1, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l130.region_id, ptr [[KERNEL_ARGS29]]) @@ -720,7 +720,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP171:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 10 // CHECK1-NEXT: store [3 x i32] [i32 1, i32 2, i32 3], ptr [[TMP171]], align 4 // CHECK1-NEXT: [[TMP172:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 11 -// CHECK1-NEXT: store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP172]], align 4 +// CHECK1-NEXT: store [3 x i32] [i32 1, i32 2, i32 3], ptr [[TMP172]], align 4 // CHECK1-NEXT: [[TMP173:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 12 // CHECK1-NEXT: store i32 0, ptr [[TMP173]], align 4 // CHECK1-NEXT: [[TMP174:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 1, i32 1, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l136.region_id, ptr [[KERNEL_ARGS37]]) @@ -2458,7 +2458,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP142:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 10 // CHECK3-NEXT: store [3 x i32] [i32 1, i32 2, i32 0], ptr [[TMP142]], align 4 // CHECK3-NEXT: [[TMP143:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 11 -// CHECK3-NEXT: store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP143]], align 4 +// CHECK3-NEXT: store [3 x i32] [i32 1, i32 2, i32 0], ptr [[TMP143]], align 4 // CHECK3-NEXT: [[TMP144:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 12 // CHECK3-NEXT: store i32 0, ptr [[TMP144]], align 4 // CHECK3-NEXT: [[TMP145:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 1, i32 1, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l130.region_id, ptr [[KERNEL_ARGS29]]) @@ -2511,7 +2511,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP169:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 10 // CHECK3-NEXT: store [3 x i32] [i32 1, i32 2, i32 3], ptr [[TMP169]], align 4 // CHECK3-NEXT: [[TMP170:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 11 -// CHECK3-NEXT: store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP170]], align 4 +// CHECK3-NEXT: store [3 x i32] [i32 1, i32 2, i32 3], ptr [[TMP170]], align 4 // CHECK3-NEXT: [[TMP171:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 12 // CHECK3-NEXT: store i32 0, ptr [[TMP171]], align 4 // CHECK3-NEXT: [[TMP172:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 1, i32 1, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l136.region_id, ptr [[KERNEL_ARGS37]]) diff --git a/clang/test/Parser/attr-order.cpp b/clang/test/Parser/attr-order.cpp index 10bad38cac64470..21e30e5b6f9df1a 100644 --- a/clang/test/Parser/attr-order.cpp +++ b/clang/test/Parser/attr-order.cpp @@ -31,3 +31,16 @@ template template [[noreturn]] __declspec(dllexport) __attribute__((cdecl)) void k(); // ok + +extern "C" { + __attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] int l(int); // ok + [[__maybe_unused__]] __attribute__ ((__warn_unused_result__)) int m(int); // ok +} + +extern "C" { + __attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] int n (int); // ok + __attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] static int o (int x) { return x; }; // ok +} + +extern "C" __attribute__ ((__warn_unused_result__)) [[__maybe_unused__]] int p(int); // ok +extern "C" [[__maybe_unused__]] __attribute__ ((__warn_unused_result__)) int q(int); // ok diff --git a/clang/test/Parser/cxx2c-variadic-friends-ext-diags.cpp b/clang/test/Parser/cxx2c-variadic-friends-ext-diags.cpp new file mode 100644 index 000000000000000..ffcc97ffd635298 --- /dev/null +++ b/clang/test/Parser/cxx2c-variadic-friends-ext-diags.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++2c -verify=compat -fsyntax-only -Wpre-c++26-compat %s +// RUN: %clang_cc1 -std=c++11 -verify=pre2c -fsyntax-only -Wc++26-extensions %s + +struct S { + friend int, long, char; // compat-warning {{variadic 'friend' declarations are incompatible with C++ standards before C++2c}} \ + // pre2c-warning {{variadic 'friend' declarations are a C++2c extension}} +}; + +template +struct TS { + friend Types...; // compat-warning {{variadic 'friend' declarations are incompatible with C++ standards before C++2c}} \ + // pre2c-warning {{variadic 'friend' declarations are a C++2c extension}} + + friend int, Types..., Types...; // compat-warning {{variadic 'friend' declarations are incompatible with C++ standards before C++2c}} \ + // pre2c-warning {{variadic 'friend' declarations are a C++2c extension}} +}; diff --git a/clang/test/Parser/cxx2c-variadic-friends.cpp b/clang/test/Parser/cxx2c-variadic-friends.cpp new file mode 100644 index 000000000000000..b7da3e611048129 --- /dev/null +++ b/clang/test/Parser/cxx2c-variadic-friends.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2c %s + +template struct TS; // #template + +struct Errors { + friend int, int; + friend int, long, char; + + // We simply diagnose and ignore the '...' here. + friend float...; // expected-error {{pack expansion does not contain any unexpanded parameter packs}} + + friend short..., unsigned, unsigned short...; // expected-error 2 {{pack expansion does not contain any unexpanded parameter packs}} + + template + friend struct TS, int; // expected-error {{a friend declaration that befriends a template must contain exactly one type-specifier}} + + double friend; // expected-error {{'friend' must appear first in a non-function declaration}} + double friend, double; // expected-error {{expected member name or ';' after declaration specifiers}} +}; + +template +struct C { template class Nested; }; + +template +struct D { template class Nested; }; + +template +struct E { template class Nested; }; + +template // expected-note {{template parameter is declared here}} +struct VS { + friend Ts...; + + friend class Ts...; // expected-error {{declaration of 'Ts' shadows template parameter}} + // expected-error@-1 {{pack expansion does not contain any unexpanded parameter packs}} + + // TODO: Fix-it hint to insert '...'. + friend Ts; // expected-error {{friend declaration contains unexpanded parameter pack}} + + template + friend Us...; // expected-error {{friend type templates must use an elaborated type}} + + template // expected-note {{is declared here}} + friend class Us...; // expected-error {{declaration of 'Us' shadows template parameter}} + + template + friend class C::template Nested...; // expected-error {{cannot specialize a dependent template}} + + template + friend class C::template Nested...; // expected-error {{cannot specialize a dependent template}} + + // Nonsense (see CWG 2917). + template + friend class C::Nested...; // expected-error {{friend declaration expands pack 'Us' that is declared it its own template parameter list}} + + template + friend class E::Nested...; // expected-error {{friend declaration expands pack 'Bs' that is declared it its own template parameter list}} + + // FIXME: Both of these should be valid, but we can't handle these at + // the moment because the NNS is dependent. + template + friend class TS::Nested...; // expected-warning {{dependent nested name specifier 'TS::' for friend template declaration is not supported; ignoring this friend declaration}} + + template + friend class D::Nested...; // expected-warning {{dependent nested name specifier 'D::' for friend class declaration is not supported; turning off access control for 'VS'}} +}; + +namespace length_mismatch { +struct A { + template + struct Nested { + struct Foo{}; + }; +}; +template +struct S { + template + struct T { + // expected-error@+2 {{pack expansion contains parameter packs 'Ts' and 'Us' that have different lengths (1 vs. 2)}} + // expected-error@+1 {{pack expansion contains parameter packs 'Ts' and 'Us' that have different lengths (2 vs. 1)}} + friend class Ts::template Nested::Foo...; + }; +}; + +void f() { + S::T s; + S::T s2; + S::T s3; // expected-note {{in instantiation of}} + S::T s4; // expected-note {{in instantiation of}} +} +} diff --git a/clang/test/Parser/parser_overflow.c b/clang/test/Parser/parser_overflow.c index 9514e808550a4b8..53c79bc06d993d9 100644 --- a/clang/test/Parser/parser_overflow.c +++ b/clang/test/Parser/parser_overflow.c @@ -1,5 +1,5 @@ // RUN: not %clang_cc1 %s -fsyntax-only -DHUGE 2>&1 | FileCheck %s -// RUN: not %clang_cc1 %s -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang_cc1 %s -fsyntax-only // RUN: not %clang_cc1 %s -fsyntax-only -fbracket-depth 299 2>&1 | FileCheck %s // RUN: %clang_cc1 %s -fsyntax-only -fbracket-depth 300 // RUN: not %clang %s -fsyntax-only -fbracket-depth=299 2>&1 | FileCheck %s @@ -15,5 +15,5 @@ void foo(void) { #endif } -// CHECK: fatal error: bracket nesting level exceeded maximum of {{256|299}} +// CHECK: fatal error: bracket nesting level exceeded maximum of {{2048|299}} // CHECK: note: use -fbracket-depth=N to increase maximum nesting level diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 72131108cb5f6ac..517702fab5b919f 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -187,8 +187,10 @@ // CHECK-NOT: __riscv_zicfilp {{.*$}} // CHECK-NOT: __riscv_zicfiss {{.*$}} // CHECK-NOT: __riscv_ztso {{.*$}} +// CHECK-NOT: __riscv_zvbc32e {{.*$}} // CHECK-NOT: __riscv_zvfbfmin {{.*$}} // CHECK-NOT: __riscv_zvfbfwma {{.*$}} +// CHECK-NOT: __riscv_zvkgs {{.*$}} // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32ia -E -dM %s \ @@ -1658,6 +1660,14 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-ZTSO-EXT %s // CHECK-ZTSO-EXT: __riscv_ztso 1000000{{$}} +// RUN: %clang --target=riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32i_zve32x_zvbc32e0p7 -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZVBC32E-EXT %s +// RUN: %clang --target=riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64i_zve32x_zvbc32e0p7 -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZVBC32E-EXT %s +// CHECK-ZVBC32E-EXT: __riscv_zvbc32e 7000{{$}} + // RUN: %clang --target=riscv32 -menable-experimental-extensions \ // RUN: -march=rv32ifzvfbfmin1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZVFBFMIN-EXT %s @@ -1674,6 +1684,14 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-ZVFBFWMA-EXT %s // CHECK-ZVFBFWMA-EXT: __riscv_zvfbfwma 1000000{{$}} +// RUN: %clang --target=riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32i_zve32x_zvkgs0p7 -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZVKGS-EXT %s +// RUN: %clang --target=riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64i_zve32x_zvkgs0p7 -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZVKGS-EXT %s +// CHECK-ZVKGS-EXT: __riscv_zvkgs 7000{{$}} + // RUN: %clang -target riscv32 -menable-experimental-extensions \ // RUN: -march=rv32izicfiss1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s diff --git a/clang/test/Sema/block-misc.c b/clang/test/Sema/block-misc.c index aea44d55a606a41..c8a34b7f3c9fd55 100644 --- a/clang/test/Sema/block-misc.c +++ b/clang/test/Sema/block-misc.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -verify %s -fblocks +// RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -verify %s -fblocks -fexperimental-new-constant-interpreter void donotwarn(void); int (^IFP) (); diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c index d3d70511b185138..126fc6f953dea2e 100644 --- a/clang/test/Sema/block-return.c +++ b/clang/test/Sema/block-return.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -pedantic -fsyntax-only %s -verify -fblocks +// RUN: %clang_cc1 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -pedantic -fsyntax-only %s -verify -fblocks -fexperimental-new-constant-interpreter extern int printf(const char *, ...); diff --git a/clang/test/Sema/c2x-nodiscard.c b/clang/test/Sema/c2x-nodiscard.c index cb33c0c242e7db9..f8b0567366465df 100644 --- a/clang/test/Sema/c2x-nodiscard.c +++ b/clang/test/Sema/c2x-nodiscard.c @@ -54,3 +54,9 @@ void test_missiles(void) { launch_missiles(); } +[[nodiscard]] int f3(); + +void GH104391() { +#define M (unsigned int) f3() + M; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +} diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c index 37b63cf4f6b3285..da2264500d76802 100644 --- a/clang/test/Sema/constant-builtins-2.c +++ b/clang/test/Sema/constant-builtins-2.c @@ -204,6 +204,53 @@ char isfpclass_snan_1 [!__builtin_isfpclass(__builtin_nans(""), 0x0002) ? 1 : char isfpclass_snan_2 [__builtin_isfpclass(__builtin_nansl(""), 0x0207) ? 1 : -1]; // ~fcFinite char isfpclass_snan_3 [!__builtin_isfpclass(__builtin_nans(""), 0x01F8) ? 1 : -1]; // fcFinite +__extension__ _Static_assert( + !__builtin_signbit(1.0) && __builtin_signbit(-1.0) && !__builtin_signbit(0.0) && __builtin_signbit(-0.0) && + !__builtin_signbitf(1.0f) && __builtin_signbitf(-1.0f) && !__builtin_signbitf(0.0f) && __builtin_signbitf(-0.0f) && + !__builtin_signbitl(1.0L) && __builtin_signbitf(-1.0L) && !__builtin_signbitf(0.0L) && __builtin_signbitf(-0.0L) && + !__builtin_signbit(1.0f) && __builtin_signbit(-1.0f) && !__builtin_signbit(0.0f) && __builtin_signbit(-0.0f) && + !__builtin_signbit(1.0L) && __builtin_signbit(-1.0L) && !__builtin_signbit(0.0L) && __builtin_signbit(-0.0L) && +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) + !__builtin_signbit(1.0q) && __builtin_signbit(-1.0q) && !__builtin_signbit(0.0q) && __builtin_signbit(-0.0q) && +#endif + 1, "" +); + +#define LESS(X, Y) \ + !__builtin_isgreater(X, Y) && __builtin_isgreater(Y, X) && \ + !__builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) && \ + __builtin_isless(X, Y) && !__builtin_isless(Y, X) && \ + __builtin_islessequal(X, Y) && !__builtin_islessequal(Y, X) && \ + __builtin_islessgreater(X, Y) && __builtin_islessgreater(Y, X) && \ + !__builtin_isunordered(X, Y) && !__builtin_isunordered(Y, X) +#define EQUAL(X, Y) \ + !__builtin_isgreater(X, Y) && !__builtin_isgreater(Y, X) && \ + __builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) && \ + !__builtin_isless(X, Y) && !__builtin_isless(Y, X) && \ + __builtin_islessequal(X, Y) && __builtin_islessequal(Y, X) && \ + !__builtin_islessgreater(X, Y) && !__builtin_islessgreater(Y, X) && \ + !__builtin_isunordered(X, Y) && !__builtin_isunordered(Y, X) +#define UNORDERED(X, Y) \ + !__builtin_isgreater(X, Y) && !__builtin_isgreater(Y, X) && \ + !__builtin_isgreaterequal(X, Y) && !__builtin_isgreaterequal(Y, X) && \ + !__builtin_isless(X, Y) && !__builtin_isless(Y, X) && \ + !__builtin_islessequal(X, Y) && !__builtin_islessequal(Y, X) && \ + !__builtin_islessgreater(X, Y) && !__builtin_islessgreater(Y, X) && \ + __builtin_isunordered(X, Y) && __builtin_isunordered(Y, X) + +__extension__ _Static_assert( + LESS(0.0, 1.0) && EQUAL(1.0, 1.0) && EQUAL(0.0, -0.0) && + UNORDERED(__builtin_nan(""), 1.0) && UNORDERED(__builtin_nan(""), __builtin_inf()) && LESS(0.0, __builtin_inf()) && + LESS(0.0f, 1.0f) && EQUAL(1.0f, 1.0f) && EQUAL(0.0f, -0.0f) && + UNORDERED(__builtin_nanf(""), 1.0f) && UNORDERED(__builtin_nanf(""), __builtin_inff()) && LESS(0.0f, __builtin_inff()) && + LESS(0.0L, 1.0L) && EQUAL(1.0L, 1.0L) && EQUAL(0.0L, -0.0L) && + UNORDERED(__builtin_nanl(""), 1.0L) && UNORDERED(__builtin_nanl(""), __builtin_infl()) && LESS(0.0L, __builtin_infl()) && +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) + LESS(0.0q, 1.0q) && EQUAL(1.0q, 1.0q) && EQUAL(0.0q, -0.0q) && +#endif + 1, "" +); + //double g19 = __builtin_powi(2.0, 4); //float g20 = __builtin_powif(2.0f, 4); //long double g21 = __builtin_powil(2.0L, 4); diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp index 98c19975095bbee..7454a01158f6b4a 100644 --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -1,8 +1,10 @@ -// RUN: %clang_cc1 -std=c++17 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify -fms-extensions -fexceptions -fcxx-exceptions -DTEST1 -// RUN: %clang_cc1 -std=c++98 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,precxx17 -fms-extensions -fexceptions -fcxx-exceptions -DTEST1 -// RUN: %clang_cc1 -std=c++11 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,precxx17 -fms-extensions -fexceptions -fcxx-exceptions -DTEST1 -// RUN: %clang_cc1 -std=c++14 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,precxx17 -fexceptions -fcxx-exceptions -DTEST2 -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -fms-compatibility -verify -DTEST3 +// RUN: %clang_cc1 -std=c++17 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,ms-union-ext -fms-extensions -fexceptions -fcxx-exceptions -DTEST1 +// RUN: %clang_cc1 -std=c++98 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,precxx17,ms-union-ext -fms-extensions -fexceptions -fcxx-exceptions -DTEST1 +// RUN: %clang_cc1 -std=c++11 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,precxx17,ms-union-ext -fms-extensions -fexceptions -fcxx-exceptions -DTEST1 +// RUN: %clang_cc1 -std=c++14 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify=expected,precxx17,ms-union-ext-disabled -fexceptions -fcxx-exceptions -DTEST2 +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -fms-compatibility -verify=expected,ms-union-ext -DTEST3 +// RUN: %clang_cc1 -std=c++17 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -verify=ms-union-ext -fms-extensions -fms-compatibility-version=18.00 +// RUN: %clang_cc1 -std=c++17 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -verify=ms-union-ext-disabled -fms-extensions -fms-compatibility-version=19.00 #if TEST1 @@ -384,11 +386,6 @@ void TestSP9() { c3.h(); // Overloaded unary op operand } -union u { - int *i1; - int &i2; // expected-warning {{union member 'i2' has reference type 'int &', which is a Microsoft extension}} -}; - // Property getter using reference. struct SP11 { __declspec(property(get=GetV)) int V; @@ -619,9 +616,12 @@ template struct A {}; template struct B : A> { A::C::D d; }; // expected-warning {{implicit 'typename' is a C++20 extension}} } -#else - -#error Unknown test mode - #endif +union u { + int *i1; + + // ms-union-ext-warning@+2 {{union member 'i2' has reference type 'int &', which is a Microsoft extension}} + // ms-union-ext-disabled-error@+1 {{union member 'i2' has reference type 'int &'}} + int &i2; +}; diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index 7db0a4d64d2596c..f4ca840cb276f9f 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++23 -verify %s namespace usage_invalid { // FIXME: Should we diagnose a void return type? @@ -9,6 +9,7 @@ namespace usage_invalid { A() [[clang::lifetimebound]]; // expected-error {{cannot be applied to a constructor}} ~A() [[clang::lifetimebound]]; // expected-error {{cannot be applied to a destructor}} static int *static_class_member() [[clang::lifetimebound]]; // expected-error {{static member function has no implicit object parameter}} + int *explicit_object(this A&) [[clang::lifetimebound]]; // expected-error {{explicit object member function has no implicit object parameter}} int not_function [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}} int [[clang::lifetimebound]] also_not_function; // expected-error {{cannot be applied to types}} }; diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index d888887bd8c6f39..44ef540f41fa8c7 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1268,6 +1268,9 @@ constexpr complex_wrap makeComplexWrap(int re, int im) { static_assert(makeComplexWrap(1,0) == complex(1), ""); static_assert(makeComplexWrap(1,0) != complex(0, 1), ""); +constexpr auto GH55390 = 1 / 65536j; // expected-note {{division by zero}} \ + // expected-error {{constexpr variable 'GH55390' must be initialized by a constant expression}} \ + // expected-warning {{imaginary constants are a GNU extension}} } namespace PR11595 { diff --git a/clang/test/SemaCXX/consteval-cleanup.cpp b/clang/test/SemaCXX/consteval-cleanup.cpp index 499c45db5017702..f7d033b2ecafa46 100644 --- a/clang/test/SemaCXX/consteval-cleanup.cpp +++ b/clang/test/SemaCXX/consteval-cleanup.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fblocks -Wno-unused-value -std=c++20 -ast-dump -verify %s -ast-dump | FileCheck %s +// RUN: %clang_cc1 -fblocks -Wno-unused-value -std=c++20 -ast-dump -verify %s -ast-dump -fexperimental-new-constant-interpreter | FileCheck %s // expected-no-diagnostics diff --git a/clang/test/SemaCXX/constexpr-vectors.cpp b/clang/test/SemaCXX/constexpr-vectors.cpp index 99b045f888d87c2..7492116f44d70f3 100644 --- a/clang/test/SemaCXX/constexpr-vectors.cpp +++ b/clang/test/SemaCXX/constexpr-vectors.cpp @@ -1,10 +1,6 @@ -// RUN: %clang_cc1 -std=c++14 -Wno-unused-value %s -disable-llvm-passes -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -Wno-uninitialized -std=c++14 -fsyntax-only -verify -// FIXME: Unfortunately there is no good way to validate that our values are -// correct since Vector types don't have operator [] implemented for constexpr. -// Instead, we need to use filecheck to ensure the emitted IR is correct. Once -// someone implements array subscript operator for these types as constexpr, -// this test should modified to jsut use static asserts. +// expected-no-diagnostics using FourCharsVecSize __attribute__((vector_size(4))) = char; using FourIntsVecSize __attribute__((vector_size(16))) = int; @@ -150,564 +146,691 @@ constexpr auto CmpBinOr(T t, U u) { return t; } +constexpr auto CmpF(float t, float u) { + return __builtin_fabs(t - u) < 0.0001; +} + // Only int vs float makes a difference here, so we only need to test 1 of each. // Test Char to make sure the mixed-nature of shifts around char is evident. void CharUsage() { constexpr auto a = FourCharsVecSize{6, 3, 2, 1} + - FourCharsVecSize{12, 15, 5, 7}; - // CHECK: store <4 x i8> + FourCharsVecSize{12, 15, 5, 7}; + static_assert(a[0] == 18 && a[1] == 18 && a[2] == 7 && a[3] == 8, ""); + constexpr auto b = FourCharsVecSize{19, 15, 13, 12} - FourCharsVecSize{13, 14, 5, 3}; - // CHECK: store <4 x i8> + static_assert(b[0] == 6 && b[1] == 1 && b[2] == 8 && b[3] == 9, ""); + constexpr auto c = FourCharsVecSize{8, 4, 2, 1} * FourCharsVecSize{3, 4, 5, 6}; - // CHECK: store <4 x i8> + static_assert(c[0] == 24 && c[1] == 16 && c[2] == 10 && c[3] == 6, ""); + constexpr auto d = FourCharsVecSize{12, 12, 10, 10} / FourCharsVecSize{6, 4, 5, 2}; - // CHECK: store <4 x i8> + static_assert(d[0] == 2 && d[1] == 3 && d[2] == 2 && d[3] == 5, ""); + constexpr auto e = FourCharsVecSize{12, 12, 10, 10} % FourCharsVecSize{6, 4, 4, 3}; - // CHECK: store <4 x i8> + static_assert(e[0] == 0 && e[1] == 0 && e[2] == 2 && e[3] == 1, ""); constexpr auto f = FourCharsVecSize{6, 3, 2, 1} + 3; - // CHECK: store <4 x i8> + static_assert(f[0] == 9 && f[1] == 6 && f[2] == 5 && f[3] == 4, ""); + constexpr auto g = FourCharsVecSize{19, 15, 12, 10} - 3; - // CHECK: store <4 x i8> + static_assert(g[0] == 16 && g[1] == 12 && g[2] == 9 && g[3] == 7, ""); + constexpr auto h = FourCharsVecSize{8, 4, 2, 1} * 3; - // CHECK: store <4 x i8> + static_assert(h[0] == 24 && h[1] == 12 && h[2] == 6 && h[3] == 3, ""); + constexpr auto j = FourCharsVecSize{12, 15, 18, 21} / 3; - // CHECK: store <4 x i8> + static_assert(j[0] == 4 && j[1] == 5 && j[2] == 6 && j[3] == 7, ""); + constexpr auto k = FourCharsVecSize{12, 17, 19, 22} % 3; - // CHECK: store <4 x i8> + static_assert(k[0] == 0 && k[1] == 2 && k[2] == 1 && k[3] == 1, ""); constexpr auto l = 3 + FourCharsVecSize{6, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(l[0] == 9 && l[1] == 6 && l[2] == 5 && l[3] == 4, ""); + constexpr auto m = 20 - FourCharsVecSize{19, 15, 12, 10}; - // CHECK: store <4 x i8> + static_assert(m[0] == 1 && m[1] == 5 && m[2] == 8 && m[3] == 10, ""); + constexpr auto n = 3 * FourCharsVecSize{8, 4, 2, 1}; - // CHECK: store <4 x i8> + static_assert(n[0] == 24 && n[1] == 12 && n[2] == 6 && n[3] == 3, ""); + constexpr auto o = 100 / FourCharsVecSize{12, 15, 18, 21}; - // CHECK: store <4 x i8> + static_assert(o[0] == 8 && o[1] == 6 && o[2] == 5 && o[3] == 4, ""); + constexpr auto p = 100 % FourCharsVecSize{12, 15, 18, 21}; - // CHECK: store <4 x i8> + static_assert(p[0] == 4 && p[1] == 10 && p[2] == 10 && p[3] == 16, ""); constexpr auto q = FourCharsVecSize{6, 3, 2, 1} << FourCharsVecSize{1, 1, 2, 2}; - // CHECK: store <4 x i8> + static_assert(q[0] == 12 && q[1] == 6 && q[2] == 8 && q[3] == 4, ""); + constexpr auto r = FourCharsVecSize{19, 15, 12, 10} >> FourCharsVecSize{1, 1, 2, 2}; - // CHECK: store <4 x i8> + static_assert(r[0] == 9 && r[1] == 7 && r[2] == 3 && r[3] == 2, ""); + constexpr auto s = FourCharsVecSize{6, 3, 5, 10} << 1; - // CHECK: store <4 x i8> + static_assert(s[0] == 12 && s[1] == 6 && s[2] == 10 && s[3] == 20, ""); + constexpr auto t = FourCharsVecSize{19, 15, 10, 20} >> 1; - // CHECK: store <4 x i8> + static_assert(t[0] == 9 && t[1] == 7 && t[2] == 5 && t[3] == 10, ""); + constexpr auto u = 12 << FourCharsVecSize{1, 2, 3, 3}; - // CHECK: store <4 x i8> + static_assert(u[0] == 24 && u[1] == 48 && u[2] == 96 && u[3] == 96, ""); + constexpr auto v = 12 >> FourCharsVecSize{1, 2, 2, 1}; - // CHECK: store <4 x i8> + static_assert(v[0] == 6 && v[1] == 3 && v[2] == 3 && v[3] == 6, ""); constexpr auto w = FourCharsVecSize{1, 2, 3, 4} < FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, ""); + constexpr auto x = FourCharsVecSize{1, 2, 3, 4} > FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[3] == -1, ""); + constexpr auto y = FourCharsVecSize{1, 2, 3, 4} <= FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, ""); + constexpr auto z = FourCharsVecSize{1, 2, 3, 4} >= FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, ""); + constexpr auto A = FourCharsVecSize{1, 2, 3, 4} == FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, ""); + constexpr auto B = FourCharsVecSize{1, 2, 3, 4} != FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, ""); constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i8> + static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, ""); + constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i8> + static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, ""); + constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i8> + static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, ""); + constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i8> + static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, ""); + constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i8> + static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, ""); + constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i8> + static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, ""); constexpr auto I = FourCharsVecSize{1, 2, 3, 4} & FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(I[0] == 0 && I[1] == 2 && I[2] == 2 && I[3] == 0, ""); + constexpr auto J = FourCharsVecSize{1, 2, 3, 4} ^ FourCharsVecSize { 4, 3, 2, 1 }; - // CHECK: store <4 x i8> + static_assert(J[0] == 5 && J[1] == 1 && J[2] == 1 && J[3] == 5, ""); + constexpr auto K = FourCharsVecSize{1, 2, 3, 4} | FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(K[0] == 5 && K[1] == 3 && K[2] == 3 && K[3] == 5, ""); + constexpr auto L = FourCharsVecSize{1, 2, 3, 4} & 3; - // CHECK: store <4 x i8> + static_assert(L[0] == 1 && L[1] == 2 && L[2] == 3 && L[3] == 0, ""); + constexpr auto M = FourCharsVecSize{1, 2, 3, 4} ^ 3; - // CHECK: store <4 x i8> + static_assert(M[0] == 2 && M[1] == 1 && M[2] == 0 && M[3] == 7, ""); + constexpr auto N = FourCharsVecSize{1, 2, 3, 4} | 3; - // CHECK: store <4 x i8> + static_assert(N[0] == 3 && N[1] == 3 && N[2] == 3 && N[3] == 7, ""); constexpr auto O = FourCharsVecSize{5, 0, 6, 0} && FourCharsVecSize{5, 5, 0, 0}; - // CHECK: store <4 x i8> + static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, ""); + constexpr auto P = FourCharsVecSize{5, 0, 6, 0} || FourCharsVecSize{5, 5, 0, 0}; - // CHECK: store <4 x i8> + static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, ""); constexpr auto Q = FourCharsVecSize{5, 0, 6, 0} && 3; - // CHECK: store <4 x i8> + static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, ""); + constexpr auto R = FourCharsVecSize{5, 0, 6, 0} || 3; - // CHECK: store <4 x i8> + static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, ""); constexpr auto T = CmpMul(a, b); - // CHECK: store <4 x i8> + static_assert(T[0] == 108 && T[1] == 18 && T[2] == 56 && T[3] == 72, ""); constexpr auto U = CmpDiv(a, b); - // CHECK: store <4 x i8> + static_assert(U[0] == 3 && U[1] == 18 && U[2] == 0 && U[3] == 0, ""); constexpr auto V = CmpRem(a, b); - // CHECK: store <4 x i8> + static_assert(V[0] == 0 && V[1] == 0 && V[2] == 7 && V[3] == 8, ""); constexpr auto X = CmpAdd(a, b); - // CHECK: store <4 x i8> + static_assert(X[0] == 24 && X[1] == 19 && X[2] == 15 && X[3] == 17, ""); constexpr auto Y = CmpSub(a, b); - // CHECK: store <4 x i8> + static_assert(Y[0] == 12 && Y[1] == 17 && Y[2] == -1 && Y[3] == -1, ""); constexpr auto InvH = -H; - // CHECK: store <4 x i8> + static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, ""); + constexpr auto Z = CmpLSH(a, InvH); - // CHECK: store <4 x i8> + static_assert(Z[0] == 36 && Z[1] == 36 && Z[2] == 7 && Z[3] == 16, ""); constexpr auto aa = CmpRSH(a, InvH); - // CHECK: store <4 x i8> + static_assert(aa[0] == 9 && aa[1] == 9 && aa[2] == 7 && aa[3] == 4, ""); constexpr auto ab = CmpBinAnd(a, b); - // CHECK: store <4 x i8> + static_assert(ab[0] == 2 && ab[1] == 0 && ab[2] == 0 && ab[3] == 8, ""); constexpr auto ac = CmpBinXOr(a, b); - // CHECK: store <4 x i8> + static_assert(ac[0] == 20 && ac[1] == 19 && ac[2] == 15 && ac[3] == 1, ""); constexpr auto ad = CmpBinOr(a, b); - // CHECK: store <4 x i8> + static_assert(ad[0] == 22 && ad[1] == 19 && ad[2] == 15 && ad[3] == 9, ""); constexpr auto ae = ~FourCharsVecSize{1, 2, 10, 20}; - // CHECK: store <4 x i8> + static_assert(ae[0] == -2 && ae[1] == -3 && ae[2] == -11 && ae[3] == -21, ""); constexpr auto af = !FourCharsVecSize{0, 1, 8, -1}; - // CHECK: store <4 x i8> + static_assert(af[0] == -1 && af[1] == 0 && af[2] == 0 && af[3] == 0, ""); } void CharExtVecUsage() { constexpr auto a = FourCharsExtVec{6, 3, 2, 1} + FourCharsExtVec{12, 15, 5, 7}; - // CHECK: store <4 x i8> + static_assert(a[0] == 18 && a[1] == 18 && a[2] == 7 && a[3] == 8, ""); + constexpr auto b = FourCharsExtVec{19, 15, 13, 12} - FourCharsExtVec{13, 14, 5, 3}; - // CHECK: store <4 x i8> + static_assert(b[0] == 6 && b[1] == 1 && b[2] == 8 && b[3] == 9, ""); + constexpr auto c = FourCharsExtVec{8, 4, 2, 1} * FourCharsExtVec{3, 4, 5, 6}; - // CHECK: store <4 x i8> + static_assert(c[0] == 24 && c[1] == 16 && c[2] == 10 && c[3] == 6, ""); + constexpr auto d = FourCharsExtVec{12, 12, 10, 10} / FourCharsExtVec{6, 4, 5, 2}; - // CHECK: store <4 x i8> + static_assert(d[0] == 2 && d[1] == 3 && d[2] == 2 && d[3] == 5, ""); + constexpr auto e = FourCharsExtVec{12, 12, 10, 10} % FourCharsExtVec{6, 4, 4, 3}; - // CHECK: store <4 x i8> + static_assert(e[0] == 0 && e[1] == 0 && e[2] == 2 && e[3] == 1, ""); constexpr auto f = FourCharsExtVec{6, 3, 2, 1} + 3; - // CHECK: store <4 x i8> + static_assert(f[0] == 9 && f[1] == 6 && f[2] == 5 && f[3] == 4, ""); + constexpr auto g = FourCharsExtVec{19, 15, 12, 10} - 3; - // CHECK: store <4 x i8> + static_assert(g[0] == 16 && g[1] == 12 && g[2] == 9 && g[3] == 7, ""); + constexpr auto h = FourCharsExtVec{8, 4, 2, 1} * 3; - // CHECK: store <4 x i8> + static_assert(h[0] == 24 && h[1] == 12 && h[2] == 6 && h[3] == 3, ""); + constexpr auto j = FourCharsExtVec{12, 15, 18, 21} / 3; - // CHECK: store <4 x i8> + static_assert(j[0] == 4 && j[1] == 5 && j[2] == 6 && j[3] == 7, ""); + constexpr auto k = FourCharsExtVec{12, 17, 19, 22} % 3; - // CHECK: store <4 x i8> + static_assert(k[0] == 0 && k[1] == 2 && k[2] == 1 && k[3] == 1, ""); constexpr auto l = 3 + FourCharsExtVec{6, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(l[0] == 9 && l[1] == 6 && l[2] == 5 && l[3] == 4, ""); + constexpr auto m = 20 - FourCharsExtVec{19, 15, 12, 10}; - // CHECK: store <4 x i8> + static_assert(m[0] == 1 && m[1] == 5 && m[2] == 8 && m[3] == 10, ""); + constexpr auto n = 3 * FourCharsExtVec{8, 4, 2, 1}; - // CHECK: store <4 x i8> + static_assert(n[0] == 24 && n[1] == 12 && n[2] == 6 && n[3] == 3, ""); + constexpr auto o = 100 / FourCharsExtVec{12, 15, 18, 21}; - // CHECK: store <4 x i8> + static_assert(o[0] == 8 && o[1] == 6 && o[2] == 5 && o[3] == 4, ""); + constexpr auto p = 100 % FourCharsExtVec{12, 15, 18, 21}; - // CHECK: store <4 x i8> + static_assert(p[0] == 4 && p[1] == 10 && p[2] == 10 && p[3] == 16, ""); constexpr auto q = FourCharsExtVec{6, 3, 2, 1} << FourCharsVecSize{1, 1, 2, 2}; - // CHECK: store <4 x i8> + static_assert(q[0] == 12 && q[1] == 6 && q[2] == 8 && q[3] == 4, ""); + constexpr auto r = FourCharsExtVec{19, 15, 12, 10} >> FourCharsExtVec{1, 1, 2, 2}; - // CHECK: store <4 x i8> + static_assert(r[0] == 9 && r[1] == 7 && r[2] == 3 && r[3] == 2, ""); + constexpr auto s = FourCharsExtVec{6, 3, 5, 10} << 1; - // CHECK: store <4 x i8> + static_assert(s[0] == 12 && s[1] == 6 && s[2] == 10 && s[3] == 20, ""); + constexpr auto t = FourCharsExtVec{19, 15, 10, 20} >> 1; - // CHECK: store <4 x i8> + static_assert(t[0] == 9 && t[1] == 7 && t[2] == 5 && t[3] == 10, ""); + constexpr auto u = 12 << FourCharsExtVec{1, 2, 3, 3}; - // CHECK: store <4 x i8> + static_assert(u[0] == 24 && u[1] == 48 && u[2] == 96 && u[3] == 96, ""); + constexpr auto v = 12 >> FourCharsExtVec{1, 2, 2, 1}; - // CHECK: store <4 x i8> + static_assert(v[0] == 6 && v[1] == 3 && v[2] == 3 && v[3] == 6, ""); constexpr auto w = FourCharsExtVec{1, 2, 3, 4} < FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, ""); + constexpr auto x = FourCharsExtVec{1, 2, 3, 4} > FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[3] == -1, ""); + constexpr auto y = FourCharsExtVec{1, 2, 3, 4} <= FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, ""); + constexpr auto z = FourCharsExtVec{1, 2, 3, 4} >= FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, ""); + constexpr auto A = FourCharsExtVec{1, 2, 3, 4} == FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, ""); + constexpr auto B = FourCharsExtVec{1, 2, 3, 4} != FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, ""); constexpr auto C = FourCharsExtVec{1, 2, 3, 4} < 3; - // CHECK: store <4 x i8> + static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, ""); + constexpr auto D = FourCharsExtVec{1, 2, 3, 4} > 3; - // CHECK: store <4 x i8> + static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, ""); + constexpr auto E = FourCharsExtVec{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i8> + static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, ""); + constexpr auto F = FourCharsExtVec{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i8> + static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, ""); + constexpr auto G = FourCharsExtVec{1, 2, 3, 4} == 3; - // CHECK: store <4 x i8> + static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, ""); + constexpr auto H = FourCharsExtVec{1, 2, 3, 4} != 3; - // CHECK: store <4 x i8> + static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, ""); constexpr auto I = FourCharsExtVec{1, 2, 3, 4} & FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(I[0] == 0 && I[1] == 2 && I[2] == 2 && I[3] == 0, ""); + constexpr auto J = FourCharsExtVec{1, 2, 3, 4} ^ FourCharsExtVec { 4, 3, 2, 1 }; - // CHECK: store <4 x i8> + static_assert(J[0] == 5 && J[1] == 1 && J[2] == 1 && J[3] == 5, ""); + constexpr auto K = FourCharsExtVec{1, 2, 3, 4} | FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> + static_assert(K[0] == 5 && K[1] == 3 && K[2] == 3 && K[3] == 5, ""); + constexpr auto L = FourCharsExtVec{1, 2, 3, 4} & 3; - // CHECK: store <4 x i8> + static_assert(L[0] == 1 && L[1] == 2 && L[2] == 3 && L[3] == 0, ""); + constexpr auto M = FourCharsExtVec{1, 2, 3, 4} ^ 3; - // CHECK: store <4 x i8> + static_assert(M[0] == 2 && M[1] == 1 && M[2] == 0 && M[3] == 7, ""); + constexpr auto N = FourCharsExtVec{1, 2, 3, 4} | 3; - // CHECK: store <4 x i8> + static_assert(N[0] == 3 && N[1] == 3 && N[2] == 3 && N[3] == 7, ""); constexpr auto O = FourCharsExtVec{5, 0, 6, 0} && FourCharsExtVec{5, 5, 0, 0}; - // CHECK: store <4 x i8> + static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, ""); + constexpr auto P = FourCharsExtVec{5, 0, 6, 0} || FourCharsExtVec{5, 5, 0, 0}; - // CHECK: store <4 x i8> + static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, ""); constexpr auto Q = FourCharsExtVec{5, 0, 6, 0} && 3; - // CHECK: store <4 x i8> + static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, ""); + constexpr auto R = FourCharsExtVec{5, 0, 6, 0} || 3; - // CHECK: store <4 x i8> + static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, ""); constexpr auto T = CmpMul(a, b); - // CHECK: store <4 x i8> + static_assert(T[0] == 108 && T[1] == 18 && T[2] == 56 && T[3] == 72, ""); constexpr auto U = CmpDiv(a, b); - // CHECK: store <4 x i8> + static_assert(U[0] == 3 && U[1] == 18 && U[2] == 0 && U[3] == 0, ""); constexpr auto V = CmpRem(a, b); - // CHECK: store <4 x i8> + static_assert(V[0] == 0 && V[1] == 0 && V[2] == 7 && V[3] == 8, ""); constexpr auto X = CmpAdd(a, b); - // CHECK: store <4 x i8> + static_assert(X[0] == 24 && X[1] == 19 && X[2] == 15 && X[3] == 17, ""); constexpr auto Y = CmpSub(a, b); - // CHECK: store <4 x i8> + static_assert(Y[0] == 12 && Y[1] == 17 && Y[2] == -1 && Y[3] == -1, ""); constexpr auto InvH = -H; - // CHECK: store <4 x i8> + static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, ""); constexpr auto Z = CmpLSH(a, InvH); - // CHECK: store <4 x i8> + static_assert(Z[0] == 36 && Z[1] == 36 && Z[2] == 7 && Z[3] == 16, ""); constexpr auto aa = CmpRSH(a, InvH); - // CHECK: store <4 x i8> + static_assert(aa[0] == 9 && aa[1] == 9 && aa[2] == 7 && aa[3] == 4, ""); constexpr auto ab = CmpBinAnd(a, b); - // CHECK: store <4 x i8> + static_assert(ab[0] == 2 && ab[1] == 0 && ab[2] == 0 && ab[3] == 8, ""); constexpr auto ac = CmpBinXOr(a, b); - // CHECK: store <4 x i8> + static_assert(ac[0] == 20 && ac[1] == 19 && ac[2] == 15 && ac[3] == 1, ""); constexpr auto ad = CmpBinOr(a, b); - // CHECK: store <4 x i8> + static_assert(ad[0] == 22 && ad[1] == 19 && ad[2] == 15 && ad[3] == 9, ""); constexpr auto ae = ~FourCharsExtVec{1, 2, 10, 20}; - // CHECK: store <4 x i8> + static_assert(ae[0] == -2 && ae[1] == -3 && ae[2] == -11 && ae[3] == -21, ""); constexpr auto af = !FourCharsExtVec{0, 1, 8, -1}; - // CHECK: store <4 x i8> + static_assert(af[0] == -1 && af[1] == 0 && af[2] == 0 && af[3] == 0, ""); } void FloatUsage() { constexpr auto a = FourFloatsVecSize{6, 3, 2, 1} + FourFloatsVecSize{12, 15, 5, 7}; - // CHECK: <4 x float> + static_assert(a[0] == 1.800000e+01 && a[1] == 1.800000e+01 && a[2] == 7.000000e+00 && a[3] == 8.000000e+00, ""); + constexpr auto b = FourFloatsVecSize{19, 15, 13, 12} - FourFloatsVecSize{13, 14, 5, 3}; - // CHECK: store <4 x float> + static_assert(b[0] == 6.000000e+00 && b[1] == 1.000000e+00 && b[2] == 8.000000e+00 && b[3] == 9.000000e+00, ""); + constexpr auto c = FourFloatsVecSize{8, 4, 2, 1} * FourFloatsVecSize{3, 4, 5, 6}; - // CHECK: store <4 x float> + static_assert(c[0] == 2.400000e+01 && c[1] == 1.600000e+01 && c[2] == 1.000000e+01 && c[3] == 6.000000e+00, ""); + constexpr auto d = FourFloatsVecSize{12, 12, 10, 10} / FourFloatsVecSize{6, 4, 5, 2}; - // CHECK: store <4 x float> + static_assert(d[0] == 2.000000e+00 && d[1] == 3.000000e+00 && d[2] == 2.000000e+00 && d[3] == 5.000000e+00, ""); constexpr auto f = FourFloatsVecSize{6, 3, 2, 1} + 3; - // CHECK: store <4 x float> + static_assert(f[0] == 9.000000e+00 && f[1] == 6.000000e+00 && f[2] == 5.000000e+00 && f[3] == 4.000000e+00, ""); + constexpr auto g = FourFloatsVecSize{19, 15, 12, 10} - 3; - // CHECK: store <4 x float> + static_assert(g[0] == 1.600000e+01 && g[1] == 1.200000e+01 && g[2] == 9.000000e+00 && g[3] == 7.000000e+00, ""); + constexpr auto h = FourFloatsVecSize{8, 4, 2, 1} * 3; - // CHECK: store <4 x float> + static_assert(h[0] == 2.400000e+01 && h[1] == 1.200000e+01 && h[2] == 6.000000e+00 && h[3] == 3.000000e+00, ""); + constexpr auto j = FourFloatsVecSize{12, 15, 18, 21} / 3; - // CHECK: store <4 x float> + static_assert(j[0] == 4.000000e+00 && j[1] == 5.000000e+00 && j[2] == 6.000000e+00 && j[3] == 7.000000e+00, ""); constexpr auto l = 3 + FourFloatsVecSize{6, 3, 2, 1}; - // CHECK: store <4 x float> + static_assert(l[0] == 9.000000e+00 && l[1] == 6.000000e+00 && l[2] == 5.000000e+00 && l[3] == 4.000000e+00, ""); + constexpr auto m = 20 - FourFloatsVecSize{19, 15, 12, 10}; - // CHECK: store <4 x float> + static_assert(m[0] == 1.000000e+00 && m[1] == 5.000000e+00 && m[2] == 8.000000e+00 && m[3] == 1.000000e+01, ""); + constexpr auto n = 3 * FourFloatsVecSize{8, 4, 2, 1}; - // CHECK: store <4 x float> + static_assert(n[0] == 2.400000e+01 && n[1] == 1.200000e+01 && n[2] == 6.000000e+00 && n[3] == 3.000000e+00, ""); + constexpr auto o = 100 / FourFloatsVecSize{12, 15, 18, 21}; - // CHECK: store <4 x float> + static_assert(CmpF(o[0], 100.0 / 12) && CmpF(o[1], 100.0 / 15) && CmpF(o[2], 100.0 / 18) && CmpF(o[3], 100.0 / 21), ""); constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} < FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, ""); + constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} > FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[3] == -1, ""); + constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, ""); + constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, ""); + constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} == FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, ""); + constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} != FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, ""); constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i32> + static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, ""); + constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i32> + static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, ""); + constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i32> + static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, ""); + constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i32> + static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, ""); + constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i32> + static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, ""); + constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i32> + static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, ""); constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} && FourFloatsVecSize{5, 5, 0, 0}; - // CHECK: store <4 x i32> + static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, ""); + constexpr auto P = FourFloatsVecSize{5, 0, 6, 0} || FourFloatsVecSize{5, 5, 0, 0}; - // CHECK: store <4 x i32> + static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, ""); constexpr auto Q = FourFloatsVecSize{5, 0, 6, 0} && 3; - // CHECK: store <4 x i32> + static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, ""); + constexpr auto R = FourFloatsVecSize{5, 0, 6, 0} || 3; - // CHECK: store <4 x i32> + static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, ""); constexpr auto T = CmpMul(a, b); - // CHECK: store <4 x float> + static_assert(T[0] == 1.080000e+02 && T[1] == 1.800000e+01 && T[2] == 5.600000e+01 && T[3] == 7.200000e+01, ""); constexpr auto U = CmpDiv(a, b); - // CHECK: store <4 x float> + static_assert(CmpF(U[0], a[0] / b[0]) && CmpF(U[1], a[1] / b[1]) && CmpF(U[2], a[2] / b[2]) && CmpF(U[3], a[3] / b[3]), ""); constexpr auto X = CmpAdd(a, b); - // CHECK: store <4 x float> + static_assert(X[0] == 2.400000e+01 && X[1] == 1.900000e+01 && X[2] == 1.500000e+01 && X[3] == 1.700000e+01, ""); constexpr auto Y = CmpSub(a, b); - // CHECK: store <4 x float> + static_assert(Y[0] == 1.200000e+01 && Y[1] == 1.700000e+01 && Y[2] == -1.000000e+00 && Y[3] == -1.000000e+00, ""); constexpr auto Z = -Y; - // CHECK: store <4 x float> + static_assert(Z[0] == -1.200000e+01 && Z[1] == -1.700000e+01 && Z[2] == 1.000000e+00 && Z[3] == 1.000000e+00, ""); // Operator ~ is illegal on floats, so no test for that. constexpr auto af = !FourFloatsVecSize{0, 1, 8, -1}; - // CHECK: store <4 x i32> + static_assert(af[0] == -1 && af[1] == 0 && af[2] == 0 && af[3] == 0, ""); } void FloatVecUsage() { constexpr auto a = FourFloatsVecSize{6, 3, 2, 1} + FourFloatsVecSize{12, 15, 5, 7}; - // CHECK: <4 x float> + static_assert(a[0] == 1.800000e+01 && a[1] == 1.800000e+01 && a[2] == 7.000000e+00 && a[3] == 8.000000e+00, ""); + constexpr auto b = FourFloatsVecSize{19, 15, 13, 12} - FourFloatsVecSize{13, 14, 5, 3}; - // CHECK: store <4 x float> + static_assert(b[0] == 6.000000e+00 && b[1] == 1.000000e+00 && b[2] == 8.000000e+00 && b[3] == 9.000000e+00, ""); + constexpr auto c = FourFloatsVecSize{8, 4, 2, 1} * FourFloatsVecSize{3, 4, 5, 6}; - // CHECK: store <4 x float> + static_assert(c[0] == 2.400000e+01 && c[1] == 1.600000e+01 && c[2] == 1.000000e+01 && c[3] == 6.000000e+00, ""); + constexpr auto d = FourFloatsVecSize{12, 12, 10, 10} / FourFloatsVecSize{6, 4, 5, 2}; - // CHECK: store <4 x float> + static_assert(d[0] == 2.000000e+00 && d[1] == 3.000000e+00 && d[2] == 2.000000e+00 && d[3] == 5.000000e+00, ""); constexpr auto f = FourFloatsVecSize{6, 3, 2, 1} + 3; - // CHECK: store <4 x float> + static_assert(f[0] == 9.000000e+00 && f[1] == 6.000000e+00 && f[2] == 5.000000e+00 && f[3] == 4.000000e+00, ""); + constexpr auto g = FourFloatsVecSize{19, 15, 12, 10} - 3; - // CHECK: store <4 x float> + static_assert(g[0] == 1.600000e+01 && g[1] == 1.200000e+01 && g[2] == 9.000000e+00 && g[3] == 7.000000e+00, ""); + constexpr auto h = FourFloatsVecSize{8, 4, 2, 1} * 3; - // CHECK: store <4 x float> + static_assert(h[0] == 2.400000e+01 && h[1] == 1.200000e+01 && h[2] == 6.000000e+00 && h[3] == 3.000000e+00, ""); + constexpr auto j = FourFloatsVecSize{12, 15, 18, 21} / 3; - // CHECK: store <4 x float> + static_assert(j[0] == 4.000000e+00 && j[1] == 5.000000e+00 && j[2] == 6.000000e+00 && j[3] == 7.000000e+00, ""); constexpr auto l = 3 + FourFloatsVecSize{6, 3, 2, 1}; - // CHECK: store <4 x float> + static_assert(l[0] == 9.000000e+00 && l[1] == 6.000000e+00 && l[2] == 5.000000e+00 && l[3] == 4.000000e+00, ""); + constexpr auto m = 20 - FourFloatsVecSize{19, 15, 12, 10}; - // CHECK: store <4 x float> + static_assert(m[0] == 1.000000e+00 && m[1] == 5.000000e+00 && m[2] == 8.000000e+00 && m[3] == 1.000000e+01, ""); + constexpr auto n = 3 * FourFloatsVecSize{8, 4, 2, 1}; - // CHECK: store <4 x float> + static_assert(n[0] == 2.400000e+01 && n[1] == 1.200000e+01 && n[2] == 6.000000e+00 && n[3] == 3.000000e+00, ""); + constexpr auto o = 100 / FourFloatsVecSize{12, 15, 18, 21}; - // CHECK: store <4 x float> + static_assert(CmpF(o[0], 100.0 / 12) && CmpF(o[1], 100.0 / 15) && CmpF(o[2], 100.0 / 18) && CmpF(o[3], 100.0 / 21), ""); constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} < FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, ""); + constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} > FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[2] == -1, ""); + constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, ""); + constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, ""); + constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} == FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, ""); + constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} != FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, ""); constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i32> + static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, ""); + constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i32> + static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, ""); + constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i32> + static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, ""); + constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i32> + static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, ""); + constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i32> + static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, ""); + constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i32> + static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, ""); constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} && FourFloatsVecSize{5, 5, 0, 0}; - // CHECK: store <4 x i32> + static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, ""); + constexpr auto P = FourFloatsVecSize{5, 0, 6, 0} || FourFloatsVecSize{5, 5, 0, 0}; - // CHECK: store <4 x i32> + static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, ""); constexpr auto Q = FourFloatsVecSize{5, 0, 6, 0} && 3; - // CHECK: store <4 x i32> + static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, ""); + constexpr auto R = FourFloatsVecSize{5, 0, 6, 0} || 3; - // CHECK: store <4 x i32> + static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, ""); constexpr auto T = CmpMul(a, b); - // CHECK: store <4 x float> + static_assert(T[0] == 1.080000e+02 && T[1] == 1.800000e+01 && T[2] == 5.600000e+01 && T[3] == 7.200000e+01, ""); constexpr auto U = CmpDiv(a, b); - // CHECK: store <4 x float> + static_assert(CmpF(U[0], a[0] / b[0]) && CmpF(U[1], a[1] / b[1]) && CmpF(U[2], a[2] / b[2]) && CmpF(U[3], a[3] / b[3]), ""); constexpr auto X = CmpAdd(a, b); - // CHECK: store <4 x float> + static_assert(X[0] == 2.400000e+01 && X[1] == 1.900000e+01 && X[2] == 1.500000e+01 && X[3] == 1.700000e+01, ""); constexpr auto Y = CmpSub(a, b); - // CHECK: store <4 x float> + static_assert(Y[0] == 1.200000e+01 && Y[1] == 1.700000e+01 && Y[2] == -1.000000e+00 && Y[3] == -1.000000e+00, ""); constexpr auto Z = -Y; - // CHECK: store <4 x float> + static_assert(Z[0] == -1.200000e+01 && Z[1] == -1.700000e+01 && Z[2] == 1.000000e+00 && Z[3] == 1.000000e+00, ""); // Operator ~ is illegal on floats, so no test for that. constexpr auto af = !FourFloatsVecSize{0, 1, 8, -1}; - // CHECK: store <4 x i32> + static_assert(af[0] == -1 && af[1] == 0 && af[2] == 0 && af[3] == 0, ""); } void I128Usage() { constexpr auto a = FourI128VecSize{1, 2, 3, 4}; - // CHECK: store <4 x i128> + static_assert(a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4, ""); + constexpr auto b = a < 3; - // CHECK: store <4 x i128> + static_assert(b[0] == -1 && b[1] == -1 && b[2] == 0 && b[3] == 0, ""); // Operator ~ is illegal on floats, so no test for that. constexpr auto c = ~FourI128VecSize{1, 2, 10, 20}; - // CHECK: store <4 x i128> + static_assert(c[0] == -2 && c[1] == -3 && c[2] == -11 && c[3] == -21, ""); constexpr auto d = !FourI128VecSize{0, 1, 8, -1}; - // CHECK: store <4 x i128> + static_assert(d[0] == -1 && d[1] == 0 && d[2] == 0 && d[3] == 0, ""); } void I128VecUsage() { constexpr auto a = FourI128ExtVec{1, 2, 3, 4}; - // CHECK: store <4 x i128> + static_assert(a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4, ""); + constexpr auto b = a < 3; - // CHECK: store <4 x i128> + static_assert(b[0] == -1 && b[1] == -1 && b[2] == 0 && b[3] == 0, ""); // Operator ~ is illegal on floats, so no test for that. constexpr auto c = ~FourI128ExtVec{1, 2, 10, 20}; - // CHECK: store <4 x i128> + static_assert(c[0] == -2 && c[1] == -3 && c[2] == -11 && c[3] == -21, ""); constexpr auto d = !FourI128ExtVec{0, 1, 8, -1}; - // CHECK: store <4 x i128> + static_assert(d[0] == -1 && d[1] == 0 && d[2] == 0 && d[3] == 0, ""); } using FourBoolsExtVec __attribute__((ext_vector_type(4))) = bool; void BoolVecUsage() { constexpr auto a = FourBoolsExtVec{true, false, true, false} < FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %a, align 1 + static_assert(a[0] == false && a[1] == false && a[2] == false && a[3] == true, ""); + constexpr auto b = FourBoolsExtVec{true, false, true, false} <= FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %b, align 1 + static_assert(b[0] == false && b[1] == true && b[2] == true && b[3] == true, ""); + constexpr auto c = FourBoolsExtVec{true, false, true, false} == FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %c, align 1 + static_assert(c[0] == false && c[1] == true && c[2] == true && c[3] == false, ""); + constexpr auto d = FourBoolsExtVec{true, false, true, false} != FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %d, align 1 + static_assert(d[0] == true && d[1] == false && d[2] == false && d[3] == true, ""); + constexpr auto e = FourBoolsExtVec{true, false, true, false} >= FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %e, align 1 + static_assert(e[0] == true && e[1] == true && e[2] == true && e[3] == false, ""); + constexpr auto f = FourBoolsExtVec{true, false, true, false} > FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %f, align 1 + static_assert(f[0] == true && f[1] == false && f[2] == false && f[3] == false, ""); + constexpr auto g = FourBoolsExtVec{true, false, true, false} & FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %g, align 1 + static_assert(g[0] == false && g[1] == false && g[2] == true && g[3] == false, ""); + constexpr auto h = FourBoolsExtVec{true, false, true, false} | FourBoolsExtVec{false, false, true, true}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %h, align 1 + static_assert(h[0] == true && h[1] == false && h[2] == true && h[3] == true, ""); + constexpr auto i = FourBoolsExtVec{true, false, true, false} ^ FourBoolsExtVec { false, false, true, true }; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %i, align 1 + static_assert(i[0] == true && i[1] == false && i[2] == false && i[3] == true, ""); + constexpr auto j = !FourBoolsExtVec{true, false, true, false}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %j, align 1 + static_assert(j[0] == false && j[1] == true && j[2] == false && j[3] == true, ""); + constexpr auto k = ~FourBoolsExtVec{true, false, true, false}; - // CHECK: store i8 bitcast (<8 x i1> to i8), ptr %k, align 1 + static_assert(k[0] == false && k[1] == true && k[2] == false && k[3] == true, ""); } diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index 45fee6514c12bc6..bfcc5991cee5aca 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -729,10 +729,10 @@ struct S2 { }; S2& S2::operator=(this int&& self, const S2&) = default; -// expected-error@-1 {{the type of the explicit object parameter of an explicitly-defaulted copy assignment operator should match the type of the class 'S2'}} +// expected-error@-1 {{the type of the explicit object parameter of an explicitly-defaulted copy assignment operator should be reference to 'S2'}} S2& S2::operator=(this int&& self, S2&&) = default; -// expected-error@-1 {{the type of the explicit object parameter of an explicitly-defaulted move assignment operator should match the type of the class 'S2'}} +// expected-error@-1 {{the type of the explicit object parameter of an explicitly-defaulted move assignment operator should be reference to 'S2'}} struct Move { Move& operator=(this int&, Move&&) = default; @@ -972,3 +972,61 @@ struct R { f(r_value_ref); // expected-error {{no matching member function for call to 'f'}} } }; + +namespace GH100329 { +struct A { + bool operator == (this const int&, const A&); +}; +bool A::operator == (this const int&, const A&) = default; +// expected-error@-1 {{invalid parameter type for defaulted equality comparison operator; found 'const int &', expected 'const GH100329::A &'}} +} // namespace GH100329 + +namespace defaulted_assign { +struct A { + A& operator=(this A, const A&) = default; + // expected-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}} + // expected-note@-2 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}} + A& operator=(this int, const A&) = default; + // expected-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}} + // expected-note@-2 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}} +}; +} // namespace defaulted_assign + +namespace defaulted_compare { +struct A { + bool operator==(this A&, const A&) = default; + // expected-error@-1 {{defaulted member equality comparison operator must be const-qualified}} + bool operator==(this const A, const A&) = default; + // expected-error@-1 {{invalid parameter type for defaulted equality comparison operator; found 'const A', expected 'const defaulted_compare::A &'}} + bool operator==(this A, A) = default; +}; +struct B { + int a; + bool operator==(this B, B) = default; +}; +static_assert(B{0} == B{0}); +static_assert(B{0} != B{1}); +template +struct X; +static_assert(__is_same(X, X)); +static_assert(!__is_same(X, X)); +} // namespace defaulted_compare + +namespace GH102025 { +struct Foo { + template + constexpr auto operator[](this T &&self, auto... i) // expected-note {{candidate template ignored: substitution failure [with T = Foo &, i:auto = <>]: member '_evaluate' used before its declaration}} + -> decltype(_evaluate(self, i...)) { + return self._evaluate(i...); + } + +private: + template + constexpr auto _evaluate(this T &&self, auto... i) -> decltype((i + ...)); +}; + +int main() { + Foo foo; + return foo[]; // expected-error {{no viable overloaded operator[] for type 'Foo'}} +} +} diff --git a/clang/test/SemaCXX/cxx2c-variadic-friends.cpp b/clang/test/SemaCXX/cxx2c-variadic-friends.cpp new file mode 100644 index 000000000000000..a4d7c8078338d2a --- /dev/null +++ b/clang/test/SemaCXX/cxx2c-variadic-friends.cpp @@ -0,0 +1,156 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2c %s + +struct A; +struct B; +struct C; + +struct S {}; +template struct TS {}; + +template +class X { + friend Pack...; + static void f() { } // expected-note {{declared private here}} +}; + +class Y { + friend A, B, C; + static void g() { } // expected-note {{declared private here}} +}; + +struct A { + A() { + X::f(); + Y::g(); + }; +}; + +struct B { + B() { + X::f(); + Y::g(); + }; +}; + +struct C { + C() { + X::f(); + Y::g(); + }; +}; + +struct D { + D() { + X::f(); // expected-error {{'f' is a private member of 'X'}} + Y::g(); // expected-error {{'g' is a private member of 'Y'}} + }; +}; + +void f1() { + A a; + B b; + C c; + D d; +} + +template +struct Z { + template