diff options
Diffstat (limited to 'clang')
72 files changed, 1796 insertions, 179 deletions
diff --git a/clang/Maintainers.rst b/clang/Maintainers.rst index 1d16ea9..847d37d 100644 --- a/clang/Maintainers.rst +++ b/clang/Maintainers.rst @@ -242,7 +242,7 @@ ARM EABI Compiler-Wide Topics -------------------- The following people are responsible for functionality that does not fit into -a single part of the compiler, but instead span multiple components within the +a single part of the compiler, but instead spans multiple components within the compiler. Attributes diff --git a/clang/docs/AddressSanitizer.rst b/clang/docs/AddressSanitizer.rst index 21e1a36..2c2131b 100644 --- a/clang/docs/AddressSanitizer.rst +++ b/clang/docs/AddressSanitizer.rst @@ -159,7 +159,7 @@ eliminating this check (``-fsanitize-address-use-after-return=never``). To summarize: ``-fsanitize-address-use-after-return=<mode>`` * ``never``: Completely disables detection of UAR errors (reduces code size). - * ``runtime``: Adds the code for detection, but it can be disable via the + * ``runtime``: Adds the code for detection, but it can be disabled via the runtime environment (``ASAN_OPTIONS=detect_stack_use_after_return=0``). * ``always``: Enables detection of UAR errors in all cases. (reduces code size, but not as much as ``never``). @@ -239,7 +239,7 @@ from adding redzones around it and detecting out of bounds accesses. AddressSanitizer also supports ``__attribute__((disable_sanitizer_instrumentation))``. This attribute -works similar to ``__attribute__((no_sanitize("address")))``, but it also +works similarly to ``__attribute__((no_sanitize("address")))``, but it also prevents instrumentation performed by other sanitizers. Suppressing Errors in Recompiled Code (Ignorelist) @@ -305,7 +305,7 @@ Limitations =========== * AddressSanitizer uses more real memory than a native run. Exact overhead - depends on the allocations sizes. The smaller the allocations you make the + depends on the allocation sizes. The smaller the allocations you make the bigger the overhead is. * AddressSanitizer uses more stack memory. We have seen up to 3x increase. * On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of diff --git a/clang/docs/BlockLanguageSpec.rst b/clang/docs/BlockLanguageSpec.rst index 3632d56..0c3a000 100644 --- a/clang/docs/BlockLanguageSpec.rst +++ b/clang/docs/BlockLanguageSpec.rst @@ -279,7 +279,7 @@ copy. The net effect is that instance variables can be mutated. The :block-term:`Block_copy` operator retains all objects held in variables of automatic storage referenced within the Block expression -(or form strong references if running under garbage collection). +(or forms strong references if running under garbage collection). Object variables of ``__block`` storage type are assumed to hold normal pointers with no provision for retain and release messages. diff --git a/clang/docs/BoundsSafety.rst b/clang/docs/BoundsSafety.rst index 519c7b6..b0f77c3 100644 --- a/clang/docs/BoundsSafety.rst +++ b/clang/docs/BoundsSafety.rst @@ -58,7 +58,7 @@ adopt, offering these properties that make it widely adoptable in practice: * It has a relatively low adoption cost. This document discusses the key designs of ``-fbounds-safety``. The document is -subject to be actively updated with a more detailed specification. +subject to active updates with a more detailed specification. Programming Model ================= @@ -574,7 +574,7 @@ When ``sizeof()`` takes a type name, the compiler doesn't apply an implicit bounds annotation on the named pointer types. This means if a bounds annotation is not specified, the evaluated pointer type is treated identically to a plain C pointer type. Therefore, ``sizeof(int*)`` remains the same with or without -``-fbounds-safety``. That said, programmers can explicitly add attribute to the +``-fbounds-safety``. That said, programmers can explicitly add attributes to the types, e.g., ``sizeof(int *__bidi_indexable)``, in which case the sizeof evaluates to the size of type ``int *__bidi_indexable`` (the value equivalent to ``3 * sizeof(int*)``). diff --git a/clang/docs/BoundsSafetyImplPlans.rst b/clang/docs/BoundsSafetyImplPlans.rst index 34276c9..b374b0a 100644 --- a/clang/docs/BoundsSafetyImplPlans.rst +++ b/clang/docs/BoundsSafetyImplPlans.rst @@ -154,7 +154,7 @@ verify its bounds safety. The implementation relies on LLVM optimizations to remove redundant run-time checks. Using this optimization strategy, if the original source code already has bounds checks, the fewer additional checks ``-fbounds-safety`` will introduce. The LLVM ``ConstraintElimination`` pass is -design to remove provable redundant checks (please check Florian Hahn’s +designed to remove provable redundant checks (please check Florian Hahn’s presentation in 2021 LLVM Dev Meeting and the implementation to learn more). In the following example, ``-fbounds-safety`` implicitly adds the redundant bounds checks that the optimizer can remove: diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 0b4a484..94d6f0d 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1673,6 +1673,16 @@ the configuration (without a prefix: ``Auto``). int abcdef; // but this isn't + * ``bool AlignPPAndNotPP`` If comments following preprocessor directive should be aligned with + comments that don't. + + .. code-block:: c++ + + true: false: + #define A // Comment vs. #define A // Comment + #define AB // Aligned #define AB // Aligned + int i; // Aligned int i; // Not aligned + .. _AllowAllArgumentsOnNextLine: diff --git a/clang/docs/ClangLinkerWrapper.rst b/clang/docs/ClangLinkerWrapper.rst index 28f48fc..3637bdb 100644 --- a/clang/docs/ClangLinkerWrapper.rst +++ b/clang/docs/ClangLinkerWrapper.rst @@ -27,7 +27,7 @@ only for the linker wrapper will be forwarded to the wrapped linker job. .. code-block:: console - USAGE: clang-linker-wrapper [options] -- <options to passed to the linker> + USAGE: clang-linker-wrapper [options] -- <options to pass to the linker> OPTIONS: --cuda-path=<dir> Set the system CUDA path diff --git a/clang/docs/ClangNVLinkWrapper.rst b/clang/docs/ClangNVLinkWrapper.rst index 2acdb05..28763b3 100644 --- a/clang/docs/ClangNVLinkWrapper.rst +++ b/clang/docs/ClangNVLinkWrapper.rst @@ -10,7 +10,7 @@ Clang nvlink Wrapper Introduction ============ -This tools works as a wrapper around the NVIDIA ``nvlink`` linker. The purpose +This tool works as a wrapper around the NVIDIA ``nvlink`` linker. The purpose of this wrapper is to provide an interface similar to the ``ld.lld`` linker while still relying on NVIDIA's proprietary linker to produce the final output. @@ -37,7 +37,7 @@ only for the linker wrapper will be forwarded to ``nvlink``. --arch <value> Specify the 'sm_' name of the target architecture. --cuda-path=<dir> Set the system CUDA path --dry-run Print generated commands without running. - --feature <value> Specify the '+ptx' freature to use for LTO. + --feature <value> Specify the '+ptx' feature to use for LTO. -g Specify that this was a debug compile. -help-hidden Display all available options -help Display available options (--help-hidden for more) diff --git a/clang/docs/ClangPlugins.rst b/clang/docs/ClangPlugins.rst index 92e41fb..3bd9e96 100644 --- a/clang/docs/ClangPlugins.rst +++ b/clang/docs/ClangPlugins.rst @@ -150,7 +150,7 @@ passed to the plugin can. -fplugin-arg-call_super_plugin-help \ test.cpp -If your plugin name contains dashes, either rename the plugin or used the +If your plugin name contains dashes, either rename the plugin or use the cc1 command line options listed below. diff --git a/clang/docs/ClangTools.rst b/clang/docs/ClangTools.rst index 3216328..b53c125 100644 --- a/clang/docs/ClangTools.rst +++ b/clang/docs/ClangTools.rst @@ -66,7 +66,7 @@ in a fast, command line interface. It can also accept flags to re-display the diagnostics in different formats with different flags, suitable for use driving an IDE or editor. Furthermore, it can be used in fixit-mode to directly apply fixit-hints offered by clang. See :doc:`HowToSetupToolingForLLVM` for -instructions on how to setup and used `clang-check`. +instructions on how to setup and use `clang-check`. ``clang-format`` ---------------- diff --git a/clang/docs/ConstantInterpreter.rst b/clang/docs/ConstantInterpreter.rst index a71ee4b..3b1bd4b 100644 --- a/clang/docs/ConstantInterpreter.rst +++ b/clang/docs/ConstantInterpreter.rst @@ -140,7 +140,7 @@ pointer goes out of scope, dead blocks are also deallocated. The lifetime of blocks is managed through 3 methods stored in the descriptor of the block: -* **CtorFn**: initializes the metadata which is store in the block, +* **CtorFn**: initializes the metadata which is stored in the block, alongside actual data. Invokes the default constructors of objects which are not trivial (``Pointer``, ``RealFP``, etc.) diff --git a/clang/docs/ControlFlowIntegrity.rst b/clang/docs/ControlFlowIntegrity.rst index baff9ab..cfe5bd8 100644 --- a/clang/docs/ControlFlowIntegrity.rst +++ b/clang/docs/ControlFlowIntegrity.rst @@ -135,7 +135,7 @@ Bad Cast Checking This scheme checks that pointer casts are made to an object of the correct dynamic type; that is, the dynamic type of the object must be a derived class of the pointee type of the cast. The checks are currently only introduced -where the class being casted to is a polymorphic class. +where the class being cast to is a polymorphic class. Bad casts are not in themselves control flow integrity violations, but they can also create security vulnerabilities, and the implementation uses many diff --git a/clang/docs/DataFlowSanitizer.rst b/clang/docs/DataFlowSanitizer.rst index 5ff50b8..154229f 100644 --- a/clang/docs/DataFlowSanitizer.rst +++ b/clang/docs/DataFlowSanitizer.rst @@ -243,7 +243,7 @@ labels of just ``v1`` and ``v2``. This signature is the same when origin tracking is disabled - in this case the dfsan_origin passed in it will always be 0. - The callback will be called when a tained value reach stack/registers + The callback will be called when a tainted value reaches stack/registers in the context of a function. Tainted values can reach a function: * via the arguments of the function * via the return value of a call that occurs in the function diff --git a/clang/docs/HardwareAssistedAddressSanitizerDesign.rst b/clang/docs/HardwareAssistedAddressSanitizerDesign.rst index 014d103..f2e76d6f 100644 --- a/clang/docs/HardwareAssistedAddressSanitizerDesign.rst +++ b/clang/docs/HardwareAssistedAddressSanitizerDesign.rst @@ -15,7 +15,7 @@ Introduction tags every 8 bytes of the application memory with a 1 byte tag (using *shadow memory*), uses *redzones* to find buffer-overflows and *quarantine* to find use-after-free. -The redzones, the quarantine, and, to a less extent, the shadow, are the +The redzones, the quarantine, and, to a lesser extent, the shadow, are the sources of AddressSanitizer's memory overhead. See the `AddressSanitizer paper`_ for details. diff --git a/clang/docs/JSONCompilationDatabase.rst b/clang/docs/JSONCompilationDatabase.rst index f543227..936ba11 100644 --- a/clang/docs/JSONCompilationDatabase.rst +++ b/clang/docs/JSONCompilationDatabase.rst @@ -54,7 +54,7 @@ python bindings also support this (since clang 3.2); see Format ====== -A compilation database is a JSON file, which consist of an array of +A compilation database is a JSON file, which consists of an array of "command objects", where each command object specifies one way a translation unit is compiled in the project. diff --git a/clang/docs/LibASTImporter.rst b/clang/docs/LibASTImporter.rst index f5d4092..e438de6 100644 --- a/clang/docs/LibASTImporter.rst +++ b/clang/docs/LibASTImporter.rst @@ -35,12 +35,12 @@ Importing one AST node copies that node into the destination ``ASTContext``. Why do we have to copy the node? Isn't enough to insert the pointer to that node into the destination context? One reason is that the "from" context may outlive the "to" context. -Also, the Clang AST consider nodes (or certain properties of nodes) equivalent if they have the same address! +Also, the Clang AST considers nodes (or certain properties of nodes) equivalent if they have the same address! The import algorithm has to ensure that the structurally equivalent nodes in the different translation units are not getting duplicated in the merged AST. E.g. if we include the definition of the vector template (``#include <vector>``) in two translation units, then their merged AST should have only one node which represents the template. Also, we have to discover *one definition rule* (ODR) violations. -For instance, if there is a class definition with the same name in both translation units, but one of the definition contains a different number of fields. +For instance, if there is a class definition with the same name in both translation units, but one of the definitions contains a different number of fields. So, we look up existing definitions, and then we check the structural equivalency on those nodes. The following pseudo-code demonstrates the basics of the import mechanism: diff --git a/clang/docs/LibASTMatchers.rst b/clang/docs/LibASTMatchers.rst index 3b9f0a6..0aa7923 100644 --- a/clang/docs/LibASTMatchers.rst +++ b/clang/docs/LibASTMatchers.rst @@ -95,7 +95,7 @@ and flexibility. ``VariadicDynCastAllOfMatcher<Base, Derived>`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Those match all nodes of type *Base* if they can be dynamically casted to +Those match all nodes of type *Base* if they can be dynamically cast to *Derived*. The names of those matchers are nouns, which closely resemble *Derived*. ``VariadicDynCastAllOfMatchers`` are the backbone of the matcher hierarchy. Most often, your match expression will start with one of them, and diff --git a/clang/docs/LibASTMatchersTutorial.rst b/clang/docs/LibASTMatchersTutorial.rst index d288368..e901eb9 100644 --- a/clang/docs/LibASTMatchersTutorial.rst +++ b/clang/docs/LibASTMatchersTutorial.rst @@ -209,7 +209,7 @@ and traversal matchers to get from one kind of AST node to another. For a complete list of AST matchers, take a look at the `AST Matcher References <LibASTMatchersReference.html>`_ -All matcher that are nouns describe entities in the AST and can be +All matchers that are nouns describe entities in the AST and can be bound, so that they can be referred to whenever a match is found. To do so, simply call the method ``bind`` on these matchers, e.g.: diff --git a/clang/docs/LibFormat.rst b/clang/docs/LibFormat.rst index 833f768..9450073 100644 --- a/clang/docs/LibFormat.rst +++ b/clang/docs/LibFormat.rst @@ -3,7 +3,7 @@ LibFormat ========= LibFormat is a library that implements automatic source code formatting based -on Clang. This documents describes the LibFormat interface and design as well +on Clang. This document describes the LibFormat interface and design as well as some basic style discussions. If you just want to use `clang-format` as a tool or integrated into an editor, diff --git a/clang/docs/MatrixTypes.rst b/clang/docs/MatrixTypes.rst index 32949c6..b3a2c8c 100644 --- a/clang/docs/MatrixTypes.rst +++ b/clang/docs/MatrixTypes.rst @@ -53,7 +53,7 @@ type of the *typedef* becomes a matrix type with the given dimensions and an element type of the former underlying type. If a declaration of a *typedef-name* has a ``matrix_type`` attribute, then all -declaration of that *typedef-name* shall have a matrix_type attribute with the +declarations of that *typedef-name* shall have a matrix_type attribute with the same element type, number of rows, and number of columns. Standard Conversions diff --git a/clang/docs/MemorySanitizer.rst b/clang/docs/MemorySanitizer.rst index 9f0d3f1..4f58142 100644 --- a/clang/docs/MemorySanitizer.rst +++ b/clang/docs/MemorySanitizer.rst @@ -176,7 +176,7 @@ for `lifetime <https://eel.is/c++draft/basic.life#1>`_ definition. This feature can be disabled with either: -#. Pass addition Clang option ``-fno-sanitize-memory-use-after-dtor`` during +#. Pass additional Clang option ``-fno-sanitize-memory-use-after-dtor`` during compilation. #. Set environment variable `MSAN_OPTIONS=poison_in_dtor=0` before running the program. diff --git a/clang/docs/Modules.rst b/clang/docs/Modules.rst index e45ee9f..0abb85c 100644 --- a/clang/docs/Modules.rst +++ b/clang/docs/Modules.rst @@ -115,7 +115,7 @@ Objective-C provides syntax for importing a module via an *@import declaration*, @import std; -The ``@import`` declaration above imports the entire contents of the ``std`` module (which would contain, e.g., the entire C or C++ standard library) and make its API available within the current translation unit. To import only part of a module, one may use dot syntax to specific a particular submodule, e.g., +The ``@import`` declaration above imports the entire contents of the ``std`` module (which would contain, e.g., the entire C or C++ standard library) and make its API available within the current translation unit. To import only part of a module, one may use dot syntax to specify a particular submodule, e.g., .. parsed-literal:: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a59f6bd..3a4e1fc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -572,6 +572,8 @@ X86 Support Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ +- More intrinsics for the following AArch64 instructions: + FCVTZ[US], FCVTN[US], FCVTM[US], FCVTP[US], FCVTA[US] Android Support ^^^^^^^^^^^^^^^ @@ -651,6 +653,7 @@ clang-format - Deprecate ``AlwaysBreak`` and ``BlockIndent`` suboptions from the ``AlignAfterOpenBracket`` option, and make ``AlignAfterOpenBracket`` a ``bool`` type. +- Add ``AlignPPAndNotPP`` suboption to ``AlignTrailingComments``. libclang -------- diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 4f50748..3296fbf 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -10068,6 +10068,152 @@ public: Expr *getSize() const { return getStmtAs<Expr>(); } }; +/// This represents 'dyn_groupprivate' clause in '#pragma omp target ...' +/// and '#pragma omp teams ...' directives. +/// +/// \code +/// #pragma omp target [...] dyn_groupprivate(a,b: N) +/// \endcode +class OMPDynGroupprivateClause : public OMPClause, public OMPClauseWithPreInit { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// Modifiers for 'dyn_groupprivate' clause. + enum { SIMPLE, FALLBACK, NUM_MODIFIERS }; + unsigned Modifiers[NUM_MODIFIERS]; + + /// Locations of modifiers. + SourceLocation ModifiersLoc[NUM_MODIFIERS]; + + /// The size of the dyn_groupprivate. + Expr *Size = nullptr; + + /// Set the first dyn_groupprivate modifier. + /// + /// \param M The modifier. + void setDynGroupprivateModifier(OpenMPDynGroupprivateClauseModifier M) { + Modifiers[SIMPLE] = M; + } + + /// Set the second dyn_groupprivate modifier. + /// + /// \param M The modifier. + void setDynGroupprivateFallbackModifier( + OpenMPDynGroupprivateClauseFallbackModifier M) { + Modifiers[FALLBACK] = M; + } + + /// Set location of the first dyn_groupprivate modifier. + void setDynGroupprivateModifierLoc(SourceLocation Loc) { + ModifiersLoc[SIMPLE] = Loc; + } + + /// Set location of the second dyn_groupprivate modifier. + void setDynGroupprivateFallbackModifierLoc(SourceLocation Loc) { + ModifiersLoc[FALLBACK] = Loc; + } + + /// Sets the location of '('. + /// + /// \param Loc Location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Set size. + /// + /// \param E Size. + void setSize(Expr *E) { Size = E; } + +public: + /// Build 'dyn_groupprivate' clause with a size expression \a Size. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param Size Size. + /// \param M1 The first modifier applied to 'dyn_groupprivate' clause. + /// \param M1Loc Location of the first modifier. + /// \param M2 The second modifier applied to 'dyn_groupprivate' clause. + /// \param M2Loc Location of the second modifier. + OMPDynGroupprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, Expr *Size, Stmt *HelperSize, + OpenMPDirectiveKind CaptureRegion, + OpenMPDynGroupprivateClauseModifier M1, + SourceLocation M1Loc, + OpenMPDynGroupprivateClauseFallbackModifier M2, + SourceLocation M2Loc) + : OMPClause(llvm::omp::OMPC_dyn_groupprivate, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Size(Size) { + setPreInitStmt(HelperSize, CaptureRegion); + Modifiers[SIMPLE] = M1; + Modifiers[FALLBACK] = M2; + ModifiersLoc[SIMPLE] = M1Loc; + ModifiersLoc[FALLBACK] = M2Loc; + } + + /// Build an empty clause. + explicit OMPDynGroupprivateClause() + : OMPClause(llvm::omp::OMPC_dyn_groupprivate, SourceLocation(), + SourceLocation()), + OMPClauseWithPreInit(this) { + Modifiers[SIMPLE] = OMPC_DYN_GROUPPRIVATE_unknown; + Modifiers[FALLBACK] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown; + } + + /// Get the first modifier of the clause. + OpenMPDynGroupprivateClauseModifier getDynGroupprivateModifier() const { + return static_cast<OpenMPDynGroupprivateClauseModifier>(Modifiers[SIMPLE]); + } + + /// Get the second modifier of the clause. + OpenMPDynGroupprivateClauseFallbackModifier + getDynGroupprivateFallbackModifier() const { + return static_cast<OpenMPDynGroupprivateClauseFallbackModifier>( + Modifiers[FALLBACK]); + } + + /// Get location of '('. + SourceLocation getLParenLoc() { return LParenLoc; } + + /// Get the first modifier location. + SourceLocation getDynGroupprivateModifierLoc() const { + return ModifiersLoc[SIMPLE]; + } + + /// Get the second modifier location. + SourceLocation getDynGroupprivateFallbackModifierLoc() const { + return ModifiersLoc[FALLBACK]; + } + + /// Get size. + Expr *getSize() { return Size; } + + /// Get size. + const Expr *getSize() const { return Size; } + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(&Size), + reinterpret_cast<Stmt **>(&Size) + 1); + } + + const_child_range children() const { + auto Children = const_cast<OMPDynGroupprivateClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_dyn_groupprivate; + } +}; + /// This represents the 'doacross' clause for the '#pragma omp ordered' /// directive. /// diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 8cb0a65..8f42742 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -4166,6 +4166,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPXDynCGroupMemClause( } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDynGroupprivateClause( + OMPDynGroupprivateClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); + TRY_TO(TraverseStmt(C->getSize())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPDoacrossClause( OMPDoacrossClause *C) { TRY_TO(VisitOMPClauseList(C)); diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 04f2e8d..3e86447 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12137,6 +12137,9 @@ def err_omp_unexpected_schedule_modifier : Error< "modifier '%0' cannot be used along with modifier '%1'">; def err_omp_schedule_nonmonotonic_static : Error< "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">; +def err_omp_incompatible_dyn_groupprivate_modifier + : Error<"modifier '%0' cannot be used along with modifier '%1' in " + "dyn_groupprivate">; def err_omp_simple_clause_incompatible_with_ordered : Error< "'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">; def err_omp_ordered_simd : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 328a0747..166b803 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -86,6 +86,12 @@ #ifndef OPENMP_GRAINSIZE_MODIFIER #define OPENMP_GRAINSIZE_MODIFIER(Name) #endif +#ifndef OPENMP_DYN_GROUPPRIVATE_MODIFIER +#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) +#endif +#ifndef OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER +#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) +#endif #ifndef OPENMP_NUMTASKS_MODIFIER #define OPENMP_NUMTASKS_MODIFIER(Name) #endif @@ -242,6 +248,14 @@ OPENMP_BIND_KIND(thread) // Modifiers for the 'grainsize' clause. OPENMP_GRAINSIZE_MODIFIER(strict) +// Modifiers for the 'dyn_groupprivate' clause. +OPENMP_DYN_GROUPPRIVATE_MODIFIER(cgroup) + +// Fallback modifiers for the 'dyn_groupprivate' clause. +OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(abort) +OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(null) +OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(default_mem) + // Modifiers for the 'num_tasks' clause. OPENMP_NUMTASKS_MODIFIER(strict) @@ -263,6 +277,8 @@ OPENMP_THREADSET_KIND(omp_team) #undef OPENMP_NUMTASKS_MODIFIER #undef OPENMP_NUMTHREADS_MODIFIER +#undef OPENMP_DYN_GROUPPRIVATE_MODIFIER +#undef OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER #undef OPENMP_GRAINSIZE_MODIFIER #undef OPENMP_BIND_KIND #undef OPENMP_ADJUST_ARGS_KIND diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index c9ddbcd..41b2c4e 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -224,6 +224,20 @@ enum OpenMPGrainsizeClauseModifier { OMPC_GRAINSIZE_unknown }; +enum OpenMPDynGroupprivateClauseModifier { +#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) OMPC_DYN_GROUPPRIVATE_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_DYN_GROUPPRIVATE_unknown +}; + +enum OpenMPDynGroupprivateClauseFallbackModifier { + OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown = OMPC_DYN_GROUPPRIVATE_unknown, +#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \ + OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_DYN_GROUPPRIVATE_FALLBACK_last +}; + enum OpenMPNumTasksClauseModifier { #define OPENMP_NUMTASKS_MODIFIER(Name) OMPC_NUMTASKS_##Name, #include "clang/Basic/OpenMPKinds.def" diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td index ef19610..e91d7ce 100644 --- a/clang/include/clang/Basic/arm_neon.td +++ b/clang/include/clang/Basic/arm_neon.td @@ -1466,26 +1466,51 @@ def SCALAR_UCVTFD : SInst<"vcvt_f64", "(1F)(1!)", "SUl">; //////////////////////////////////////////////////////////////////////////////// // Scalar Floating-point Converts def SCALAR_FCVTXN : IInst<"vcvtx_f32", "(1F<)(1!)", "Sd">; -def SCALAR_FCVTNSS : SInst<"vcvtn_s32", "(1S)1", "Sf">; -def SCALAR_FCVTNUS : SInst<"vcvtn_u32", "(1U)1", "Sf">; -def SCALAR_FCVTNSD : SInst<"vcvtn_s64", "(1S)1", "Sd">; -def SCALAR_FCVTNUD : SInst<"vcvtn_u64", "(1U)1", "Sd">; -def SCALAR_FCVTMSS : SInst<"vcvtm_s32", "(1S)1", "Sf">; -def SCALAR_FCVTMUS : SInst<"vcvtm_u32", "(1U)1", "Sf">; -def SCALAR_FCVTMSD : SInst<"vcvtm_s64", "(1S)1", "Sd">; -def SCALAR_FCVTMUD : SInst<"vcvtm_u64", "(1U)1", "Sd">; -def SCALAR_FCVTASS : SInst<"vcvta_s32", "(1S)1", "Sf">; -def SCALAR_FCVTAUS : SInst<"vcvta_u32", "(1U)1", "Sf">; -def SCALAR_FCVTASD : SInst<"vcvta_s64", "(1S)1", "Sd">; -def SCALAR_FCVTAUD : SInst<"vcvta_u64", "(1U)1", "Sd">; -def SCALAR_FCVTPSS : SInst<"vcvtp_s32", "(1S)1", "Sf">; -def SCALAR_FCVTPUS : SInst<"vcvtp_u32", "(1U)1", "Sf">; -def SCALAR_FCVTPSD : SInst<"vcvtp_s64", "(1S)1", "Sd">; -def SCALAR_FCVTPUD : SInst<"vcvtp_u64", "(1U)1", "Sd">; -def SCALAR_FCVTZSS : SInst<"vcvt_s32", "(1S)1", "Sf">; -def SCALAR_FCVTZUS : SInst<"vcvt_u32", "(1U)1", "Sf">; -def SCALAR_FCVTZSD : SInst<"vcvt_s64", "(1S)1", "Sd">; -def SCALAR_FCVTZUD : SInst<"vcvt_u64", "(1U)1", "Sd">; + +def SCALAR_FCVTN_F32toSS : SInst<"vcvtn_s32", "(1S)1", "Sf">; +def SCALAR_FCVTN_F32toUS : SInst<"vcvtn_u32", "(1U)1", "Sf">; +def SCALAR_FCVTN_F64toSS : SInst<"vcvtn_s32", "(1S<)1", "Sd">; +def SCALAR_FCVTN_F64toUS : SInst<"vcvtn_u32", "(1U<)1", "Sd">; +def SCALAR_FCVTN_F32toSD : SInst<"vcvtn_s64", "(1S>)1", "Sf">; +def SCALAR_FCVTN_F32toUD : SInst<"vcvtn_u64", "(1U>)1", "Sf">; +def SCALAR_FCVTN_F64toSD : SInst<"vcvtn_s64", "(1S)1", "Sd">; +def SCALAR_FCVTN_F64toUD : SInst<"vcvtn_u64", "(1U)1", "Sd">; + +def SCALAR_FCVTM_F32toSS : SInst<"vcvtm_s32", "(1S)1", "Sf">; +def SCALAR_FCVTM_F32toUS : SInst<"vcvtm_u32", "(1U)1", "Sf">; +def SCALAR_FCVTM_F64toSS : SInst<"vcvtm_s32", "(1S<)1", "Sd">; +def SCALAR_FCVTM_F64toUS : SInst<"vcvtm_u32", "(1U<)1", "Sd">; +def SCALAR_FCVTM_F32toSD : SInst<"vcvtm_s64", "(1S>)1", "Sf">; +def SCALAR_FCVTM_F32toUD : SInst<"vcvtm_u64", "(1U>)1", "Sf">; +def SCALAR_FCVTM_F64toSD : SInst<"vcvtm_s64", "(1S)1", "Sd">; +def SCALAR_FCVTM_F64toUD : SInst<"vcvtm_u64", "(1U)1", "Sd">; + +def SCALAR_FCVTA_F32toSS : SInst<"vcvta_s32", "(1S)1", "Sf">; +def SCALAR_FCVTA_F32toUS : SInst<"vcvta_u32", "(1U)1", "Sf">; +def SCALAR_FCVTA_F64toSS : SInst<"vcvta_s32", "(1S<)1", "Sd">; +def SCALAR_FCVTA_F64toUS : SInst<"vcvta_u32", "(1U<)1", "Sd">; +def SCALAR_FCVTA_F32toSD : SInst<"vcvta_s64", "(1S>)1", "Sf">; +def SCALAR_FCVTA_F32toUD : SInst<"vcvta_u64", "(1U>)1", "Sf">; +def SCALAR_FCVTA_F64toSD : SInst<"vcvta_s64", "(1S)1", "Sd">; +def SCALAR_FCVTA_F64toUD : SInst<"vcvta_u64", "(1U)1", "Sd">; + +def SCALAR_FCVTP_F32toSS : SInst<"vcvtp_s32", "(1S)1", "Sf">; +def SCALAR_FCVTP_F32toUS : SInst<"vcvtp_u32", "(1U)1", "Sf">; +def SCALAR_FCVTP_F64toSS : SInst<"vcvtp_s32", "(1S<)1", "Sd">; +def SCALAR_FCVTP_F64toUS : SInst<"vcvtp_u32", "(1U<)1", "Sd">; +def SCALAR_FCVTP_F32toSD : SInst<"vcvtp_s64", "(1S>)1", "Sf">; +def SCALAR_FCVTP_F32toUD : SInst<"vcvtp_u64", "(1U>)1", "Sf">; +def SCALAR_FCVTP_F64toSD : SInst<"vcvtp_s64", "(1S)1", "Sd">; +def SCALAR_FCVTP_F64toUD : SInst<"vcvtp_u64", "(1U)1", "Sd">; + +def SCALAR_FCVTZ_F32toSS : SInst<"vcvt_s32", "(1S)1", "Sf">; +def SCALAR_FCVTZ_F32toUS : SInst<"vcvt_u32", "(1U)1", "Sf">; +def SCALAR_FCVTZ_F64toSS : SInst<"vcvt_s32", "(1S<)1", "Sd">; +def SCALAR_FCVTZ_F64toUS : SInst<"vcvt_u32", "(1U<)1", "Sd">; +def SCALAR_FCVTZ_F32toSD : SInst<"vcvt_s64", "(1S>)1", "Sf">; +def SCALAR_FCVTZ_F32toUD : SInst<"vcvt_u64", "(1U>)1", "Sf">; +def SCALAR_FCVTZ_F64toSD : SInst<"vcvt_s64", "(1S)1", "Sd">; +def SCALAR_FCVTZ_F64toUD : SInst<"vcvt_u64", "(1U)1", "Sd">; //////////////////////////////////////////////////////////////////////////////// // Scalar Floating-point Reciprocal Estimate @@ -1896,6 +1921,14 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "f def VFMLSL_LANEQ_HIGH : SOpInst<"vfmlsl_laneq_high", "(F>)(F>)F(FQ)I", "hQh", OP_FMLSL_LN_Hi>; } +let ArchGuard = "defined(__aarch64__)", TargetGuard = "f8f16mm,neon" in { + def VMMLA_F16_MF8 : VInst<"vmmla_f16_mf8_fpm", "(>F)(>F)..V", "Qm">; +} + +let ArchGuard = "defined(__aarch64__)", TargetGuard = "f8f32mm,neon" in { + def VMMLA_F32_MF8 : VInst<"vmmla_f32_mf8_fpm", "(>>F)(>>F)..V", "Qm">; +} + let TargetGuard = "i8mm,neon" in { def VMMLA : SInst<"vmmla", "..(<<)(<<)", "QUiQi">; def VUSMMLA : SInst<"vusmmla", "..(<<U)(<<)", "Qi">; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index f246def..b6f124f 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -601,9 +601,19 @@ struct FormatStyle { /// int abcdef; // but this isn't /// \endcode unsigned OverEmptyLines; + /// If comments following preprocessor directive should be aligned with + /// comments that don't. + /// \code + /// true: false: + /// #define A // Comment vs. #define A // Comment + /// #define AB // Aligned #define AB // Aligned + /// int i; // Aligned int i; // Not aligned + /// \endcode + bool AlignPPAndNotPP; bool operator==(const TrailingCommentsAlignmentStyle &R) const { - return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines; + return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines && + AlignPPAndNotPP == R.AlignPPAndNotPP; } bool operator!=(const TrailingCommentsAlignmentStyle &R) const { return !(*this == R); diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 2403cbb..18ad7bf 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -946,6 +946,12 @@ public: DependencyCollectors.push_back(std::move(Listener)); } + void clearDependencyCollectors() { DependencyCollectors.clear(); } + + std::vector<std::shared_ptr<DependencyCollector>> &getDependencyCollectors() { + return DependencyCollectors; + } + void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS); ModuleCache &getModuleCache() const { return *ModCache; } diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 73308c0..87a9f0d 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -320,15 +320,6 @@ protected: bool hasPCHSupport() const override { return true; } }; -class GetDependenciesByModuleNameAction : public PreprocessOnlyAction { - StringRef ModuleName; - void ExecuteAction() override; - -public: - GetDependenciesByModuleNameAction(StringRef ModuleName) - : ModuleName(ModuleName) {} -}; - //===----------------------------------------------------------------------===// // HLSL Specific Actions //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 4120022..b1c648e 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1327,6 +1327,7 @@ public: std::move(Callbacks)); Callbacks = std::move(C); } + void removePPCallbacks() { Callbacks.reset(); } /// \} /// Get the number of tokens processed so far. diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index ba12b40..e5628e8 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -1411,6 +1411,13 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on a well-formed 'dyn_groupprivate' clause. + OMPClause *ActOnOpenMPDynGroupprivateClause( + OpenMPDynGroupprivateClauseModifier M1, + OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, + SourceLocation M2Loc, SourceLocation EndLoc); + /// Called on well-formed 'doacross' clause. OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h index f222ded..ed562f4 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h @@ -154,11 +154,52 @@ public: /// Given a compilation context specified via the Clang driver command-line, /// gather modular dependencies of module with the given name, and return the /// information needed for explicit build. + /// TODO: this method should be removed as soon as Swift and our C-APIs adopt + /// CompilerInstanceWithContext. We are keeping it here so that it is easier + /// to coordinate with Swift and C-API changes. llvm::Expected<TranslationUnitDeps> getModuleDependencies( StringRef ModuleName, const std::vector<std::string> &CommandLine, StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput); + /// The following three methods provide a new interface to perform + /// by name dependency scan. The new interface's intention is to improve + /// dependency scanning performance when a sequence of name is looked up + /// with the same current working directory and the command line. + + /// @brief Initializing the context and the compiler instance. + /// This method must be called before calling + /// computeDependenciesByNameWithContext. + /// @param CWD The current working directory used during the scan. + /// @param CommandLine The commandline used for the scan. + /// @return Error if the initializaiton fails. + llvm::Error initializeCompilerInstanceWithContext( + StringRef CWD, const std::vector<std::string> &CommandLine); + + /// @brief Computes the dependeny for the module named ModuleName. + /// @param ModuleName The name of the module for which this method computes + ///. dependencies. + /// @param AlreadySeen This stores modules which have previously been + /// reported. Use the same instance for all calls to this + /// function for a single \c DependencyScanningTool in a + /// single build. Note that this parameter is not part of + /// the context because it can be shared across different + /// worker threads and each worker thread may update it. + /// @param LookupModuleOutput This function is called to fill in + /// "-fmodule-file=", "-o" and other output + /// arguments for dependencies. + /// @return An instance of \c TranslationUnitDeps if the scan is successful. + /// Otherwise it returns an error. + llvm::Expected<TranslationUnitDeps> computeDependenciesByNameWithContext( + StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen, + LookupModuleOutputCallback LookupModuleOutput); + + /// @brief This method finializes the compiler instance. It finalizes the + /// diagnostics and deletes the compiler instance. Call this method + /// once all names for a same commandline are scanned. + /// @return Error if an error occured during finalization. + llvm::Error finalizeCompilerInstanceWithContext(); + llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); } private: diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h index 6060e4b..e2c353a 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h @@ -29,6 +29,7 @@ namespace tooling { namespace dependencies { class DependencyScanningWorkerFilesystem; +class CompilerInstanceWithContext; /// A command-line tool invocation that is part of building a TU. /// @@ -89,6 +90,8 @@ public: DependencyScanningWorker(DependencyScanningService &Service, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS); + ~DependencyScanningWorker(); + /// Run the dependency scanning tool for a given clang driver command-line, /// and report the discovered dependencies to the provided consumer. If /// TUBuffer is not nullopt, it is used as TU input for the dependency @@ -104,18 +107,6 @@ public: std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt); /// Run the dependency scanning tool for a given clang driver command-line - /// for a specific module. - /// - /// \returns false if clang errors occurred (with diagnostics reported to - /// \c DiagConsumer), true otherwise. - bool computeDependencies(StringRef WorkingDirectory, - const std::vector<std::string> &CommandLine, - DependencyConsumer &DepConsumer, - DependencyActionController &Controller, - DiagnosticConsumer &DiagConsumer, - StringRef ModuleName); - - /// Run the dependency scanning tool for a given clang driver command-line /// for a specific translation unit via file system or memory buffer. /// /// \returns A \c StringError with the diagnostic output if clang errors @@ -125,16 +116,46 @@ public: DependencyConsumer &Consumer, DependencyActionController &Controller, std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt); - /// Run the dependency scanning tool for a given clang driver command-line - /// for a specific module. - /// - /// \returns A \c StringError with the diagnostic output if clang errors - /// occurred, success otherwise. - llvm::Error computeDependencies(StringRef WorkingDirectory, - const std::vector<std::string> &CommandLine, - DependencyConsumer &Consumer, - DependencyActionController &Controller, - StringRef ModuleName); + /// The three method below implements a new interface for by name + /// dependency scanning. They together enable the dependency scanning worker + /// to more effectively perform scanning for a sequence of modules + /// by name when the CWD and CommandLine do not change across the queries. + + /// @brief Initializing the context and the compiler instance. + /// @param CWD The current working directory used during the scan. + /// @param CommandLine The commandline used for the scan. + /// @return Error if the initializaiton fails. + llvm::Error initializeCompilerInstanceWithContextOrError( + StringRef CWD, const std::vector<std::string> &CommandLine); + + /// @brief Performaces dependency scanning for the module whose name is + /// specified. + /// @param ModuleName The name of the module whose dependency will be + /// scanned. + /// @param Consumer The dependency consumer that stores the results. + /// @param Controller The controller for the dependency scanning action. + /// @return Error if the scanner incurs errors. + llvm::Error computeDependenciesByNameWithContextOrError( + StringRef ModuleName, DependencyConsumer &Consumer, + DependencyActionController &Controller); + + /// @brief Finalizes the diagnostics engine and deletes the compiler instance. + /// @return Error if errors occur during finalization. + llvm::Error finalizeCompilerInstanceWithContextOrError(); + + /// The three methods below provides the same functionality as the + /// three methods above. Instead of returning `llvm::Error`s, these + /// three methods return a flag to indicate if the call is successful. + /// The initialization function asks the client for a DiagnosticsConsumer + /// that it direct the diagnostics to. + bool initializeCompilerInstanceWithContext( + StringRef CWD, const std::vector<std::string> &CommandLine, + DiagnosticConsumer *DC = nullptr); + bool + computeDependenciesByNameWithContext(StringRef ModuleName, + DependencyConsumer &Consumer, + DependencyActionController &Controller); + bool finalizeCompilerInstance(); llvm::vfs::FileSystem &getVFS() const { return *BaseFS; } @@ -151,14 +172,16 @@ private: /// (passed in the constructor). llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS; + friend CompilerInstanceWithContext; + std::unique_ptr<CompilerInstanceWithContext> CIWithContext; + /// Private helper functions. bool scanDependencies(StringRef WorkingDirectory, const std::vector<std::string> &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, - llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, - std::optional<StringRef> ModuleName); + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS); }; } // end namespace dependencies diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index 4136cb7..b0a91b6 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -288,6 +288,8 @@ public: void attachToPreprocessor(Preprocessor &PP) override; void attachToASTReader(ASTReader &R) override; + PPCallbacks *getPPCallbacks() { return CollectorPPPtr; } + /// Apply any changes implied by the discovered dependencies to the given /// invocation, (e.g. disable implicit modules, add explicit module paths). void applyDiscoveredDependencies(CompilerInvocation &CI); @@ -339,6 +341,11 @@ private: std::optional<P1689ModuleInfo> ProvidedStdCXXModule; std::vector<P1689ModuleInfo> RequiredStdCXXModules; + /// A pointer to the preprocessor callback so we can invoke it directly + /// if needed. The callback is created and added to a Preprocessor instance by + /// attachToPreprocessor and the Preprocessor instance owns it. + ModuleDepCollectorPP *CollectorPPPtr = nullptr; + /// Checks whether the module is known as being prebuilt. bool isPrebuiltModule(const Module *M); diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 59d9459..0640fed 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -105,6 +105,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { return static_cast<const OMPFilterClause *>(C); case OMPC_ompx_dyn_cgroup_mem: return static_cast<const OMPXDynCGroupMemClause *>(C); + case OMPC_dyn_groupprivate: + return static_cast<const OMPDynGroupprivateClause *>(C); case OMPC_message: return static_cast<const OMPMessageClause *>(C); case OMPC_default: @@ -2857,6 +2859,24 @@ void OMPClausePrinter::VisitOMPXDynCGroupMemClause( OS << ")"; } +void OMPClausePrinter::VisitOMPDynGroupprivateClause( + OMPDynGroupprivateClause *Node) { + OS << "dyn_groupprivate("; + if (Node->getDynGroupprivateModifier() != OMPC_DYN_GROUPPRIVATE_unknown) { + OS << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, + Node->getDynGroupprivateModifier()); + if (Node->getDynGroupprivateFallbackModifier() != + OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown) { + OS << ", "; + OS << getOpenMPSimpleClauseTypeName( + OMPC_dyn_groupprivate, Node->getDynGroupprivateFallbackModifier()); + } + OS << ": "; + } + Node->getSize()->printPretty(OS, nullptr, Policy, 0); + OS << ')'; +} + void OMPClausePrinter::VisitOMPDoacrossClause(OMPDoacrossClause *Node) { OS << "doacross("; OpenMPDoacrossClauseModifier DepType = Node->getDependenceType(); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c909e1b..4a8c638 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -968,6 +968,12 @@ void OMPClauseProfiler::VisitOMPXDynCGroupMemClause( if (Expr *Size = C->getSize()) Profiler->VisitStmt(Size); } +void OMPClauseProfiler::VisitOMPDynGroupprivateClause( + const OMPDynGroupprivateClause *C) { + VisitOMPClauseWithPreInit(C); + if (auto *Size = C->getSize()) + Profiler->VisitStmt(Size); +} void OMPClauseProfiler::VisitOMPDoacrossClause(const OMPDoacrossClause *C) { VisitOMPClauseList(C); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 3d41f2d..8e60fc2 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -196,6 +196,16 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str, return OMPC_GRAINSIZE_unknown; return Type; } + case OMPC_dyn_groupprivate: { + return llvm::StringSwitch<unsigned>(Str) +#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) \ + .Case(#Name, OMPC_DYN_GROUPPRIVATE_##Name) +#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \ + .Case(#Name, OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name) \ + .Case("fallback(" #Name ")", OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_DYN_GROUPPRIVATE_unknown); + } case OMPC_num_tasks: { unsigned Type = llvm::StringSwitch<unsigned>(Str) #define OPENMP_NUMTASKS_MODIFIER(Name) .Case(#Name, OMPC_NUMTASKS_##Name) @@ -544,6 +554,20 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, #include "clang/Basic/OpenMPKinds.def" } llvm_unreachable("Invalid OpenMP 'grainsize' clause modifier"); + case OMPC_dyn_groupprivate: + switch (Type) { + case OMPC_DYN_GROUPPRIVATE_unknown: + case OMPC_DYN_GROUPPRIVATE_FALLBACK_last: + return "unknown"; +#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) \ + case OMPC_DYN_GROUPPRIVATE_##Name: \ + return #Name; +#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \ + case OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name: \ + return "fallback(" #Name ")"; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'dyn_groupprivate' clause modifier"); case OMPC_num_tasks: switch (Type) { case OMPC_NUMTASKS_unknown: diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 1eb7199..7bb8c21 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -66,7 +66,7 @@ static mlir::LogicalResult emitStmtWithResult(CIRGenFunction &cgf, mlir::LogicalResult CIRGenFunction::emitCompoundStmtWithoutScope( const CompoundStmt &s, Address *lastValue, AggValueSlot slot) { mlir::LogicalResult result = mlir::success(); - const Stmt *exprResult = s.getStmtExprResult(); + const Stmt *exprResult = s.body_back(); assert((!lastValue || (lastValue && exprResult)) && "If lastValue is not null then the CompoundStmt must have a " "StmtExprResult"); diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index 15fa78d..d4b0b81 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -590,6 +590,7 @@ struct ARMVectorIntrinsicInfo { Intrinsic::LLVMIntrinsic, Intrinsic::AltLLVMIntrinsic, \ TypeModifier } +// clang-format off static const ARMVectorIntrinsicInfo ARMSIMDIntrinsicMap [] = { NEONMAP1(__a32_vcvt_bf16_f32, arm_neon_vcvtfp2bf, 0), NEONMAP0(splat_lane_v), @@ -1217,35 +1218,55 @@ static const ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = { NEONMAP1(vcales_f32, aarch64_neon_facge, AddRetType | Add1ArgType), NEONMAP1(vcaltd_f64, aarch64_neon_facgt, AddRetType | Add1ArgType), NEONMAP1(vcalts_f32, aarch64_neon_facgt, AddRetType | Add1ArgType), + NEONMAP1(vcvtad_s32_f64, aarch64_neon_fcvtas, AddRetType | Add1ArgType), NEONMAP1(vcvtad_s64_f64, aarch64_neon_fcvtas, AddRetType | Add1ArgType), + NEONMAP1(vcvtad_u32_f64, aarch64_neon_fcvtau, AddRetType | Add1ArgType), NEONMAP1(vcvtad_u64_f64, aarch64_neon_fcvtau, AddRetType | Add1ArgType), NEONMAP1(vcvtas_s32_f32, aarch64_neon_fcvtas, AddRetType | Add1ArgType), + NEONMAP1(vcvtas_s64_f32, aarch64_neon_fcvtas, AddRetType | Add1ArgType), NEONMAP1(vcvtas_u32_f32, aarch64_neon_fcvtau, AddRetType | Add1ArgType), + NEONMAP1(vcvtas_u64_f32, aarch64_neon_fcvtau, AddRetType | Add1ArgType), NEONMAP1(vcvtd_n_f64_s64, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType), NEONMAP1(vcvtd_n_f64_u64, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType), NEONMAP1(vcvtd_n_s64_f64, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType), NEONMAP1(vcvtd_n_u64_f64, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType), + NEONMAP1(vcvtd_s32_f64, aarch64_neon_fcvtzs, AddRetType | Add1ArgType), NEONMAP1(vcvtd_s64_f64, aarch64_neon_fcvtzs, AddRetType | Add1ArgType), + NEONMAP1(vcvtd_u32_f64, aarch64_neon_fcvtzu, AddRetType | Add1ArgType), NEONMAP1(vcvtd_u64_f64, aarch64_neon_fcvtzu, AddRetType | Add1ArgType), NEONMAP0(vcvth_bf16_f32), + NEONMAP1(vcvtmd_s32_f64, aarch64_neon_fcvtms, AddRetType | Add1ArgType), NEONMAP1(vcvtmd_s64_f64, aarch64_neon_fcvtms, AddRetType | Add1ArgType), + NEONMAP1(vcvtmd_u32_f64, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), NEONMAP1(vcvtmd_u64_f64, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), NEONMAP1(vcvtms_s32_f32, aarch64_neon_fcvtms, AddRetType | Add1ArgType), + NEONMAP1(vcvtms_s64_f32, aarch64_neon_fcvtms, AddRetType | Add1ArgType), NEONMAP1(vcvtms_u32_f32, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), + NEONMAP1(vcvtms_u64_f32, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), + NEONMAP1(vcvtnd_s32_f64, aarch64_neon_fcvtns, AddRetType | Add1ArgType), NEONMAP1(vcvtnd_s64_f64, aarch64_neon_fcvtns, AddRetType | Add1ArgType), + NEONMAP1(vcvtnd_u32_f64, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), NEONMAP1(vcvtnd_u64_f64, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), NEONMAP1(vcvtns_s32_f32, aarch64_neon_fcvtns, AddRetType | Add1ArgType), + NEONMAP1(vcvtns_s64_f32, aarch64_neon_fcvtns, AddRetType | Add1ArgType), NEONMAP1(vcvtns_u32_f32, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), + NEONMAP1(vcvtns_u64_f32, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), + NEONMAP1(vcvtpd_s32_f64, aarch64_neon_fcvtps, AddRetType | Add1ArgType), NEONMAP1(vcvtpd_s64_f64, aarch64_neon_fcvtps, AddRetType | Add1ArgType), + NEONMAP1(vcvtpd_u32_f64, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), NEONMAP1(vcvtpd_u64_f64, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), NEONMAP1(vcvtps_s32_f32, aarch64_neon_fcvtps, AddRetType | Add1ArgType), + NEONMAP1(vcvtps_s64_f32, aarch64_neon_fcvtps, AddRetType | Add1ArgType), NEONMAP1(vcvtps_u32_f32, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), + NEONMAP1(vcvtps_u64_f32, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), NEONMAP1(vcvts_n_f32_s32, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType), NEONMAP1(vcvts_n_f32_u32, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType), NEONMAP1(vcvts_n_s32_f32, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType), NEONMAP1(vcvts_n_u32_f32, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType), NEONMAP1(vcvts_s32_f32, aarch64_neon_fcvtzs, AddRetType | Add1ArgType), + NEONMAP1(vcvts_s64_f32, aarch64_neon_fcvtzs, AddRetType | Add1ArgType), NEONMAP1(vcvts_u32_f32, aarch64_neon_fcvtzu, AddRetType | Add1ArgType), + NEONMAP1(vcvts_u64_f32, aarch64_neon_fcvtzu, AddRetType | Add1ArgType), NEONMAP1(vcvtxd_f32_f64, aarch64_sisd_fcvtxn, 0), NEONMAP1(vmaxnmv_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), NEONMAP1(vmaxnmvq_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), @@ -1446,6 +1467,7 @@ static const ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = { NEONMAP1(vrsqrteh_f16, aarch64_neon_frsqrte, Add1ArgType), NEONMAP1(vrsqrtsh_f16, aarch64_neon_frsqrts, Add1ArgType), }; +// clang-format on // Some intrinsics are equivalent for codegen. static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = { @@ -7624,6 +7646,16 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, Int = Intrinsic::aarch64_neon_vluti4q_laneq_x2; return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vluti4q_laneq_x2"); } + case NEON::BI__builtin_neon_vmmlaq_f16_mf8_fpm: + return EmitFP8NeonCall(Intrinsic::aarch64_neon_fmmla, + {llvm::FixedVectorType::get(HalfTy, 8), + llvm::FixedVectorType::get(Int8Ty, 16)}, + Ops, E, "fmmla"); + case NEON::BI__builtin_neon_vmmlaq_f32_mf8_fpm: + return EmitFP8NeonCall(Intrinsic::aarch64_neon_fmmla, + {llvm::FixedVectorType::get(FloatTy, 4), + llvm::FixedVectorType::get(Int8Ty, 16)}, + Ops, E, "fmmla"); case NEON::BI__builtin_neon_vcvt1_low_bf16_mf8_fpm: ExtractLow = true; [[fallthrough]]; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index dd14fcd..9bbb33c 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -876,27 +876,28 @@ template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> { FormatStyle::TrailingCommentsAlignmentStyle &Value) { IO.enumCase(Value, "Leave", FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Leave, 0})); + {FormatStyle::TCAS_Leave, 0, true})); IO.enumCase(Value, "Always", FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Always, 0})); + {FormatStyle::TCAS_Always, 0, true})); IO.enumCase(Value, "Never", FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Never, 0})); + {FormatStyle::TCAS_Never, 0, true})); // For backwards compatibility IO.enumCase(Value, "true", FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Always, 0})); + {FormatStyle::TCAS_Always, 0, true})); IO.enumCase(Value, "false", FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Never, 0})); + {FormatStyle::TCAS_Never, 0, true})); } static void mapping(IO &IO, FormatStyle::TrailingCommentsAlignmentStyle &Value) { + IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP); IO.mapOptional("Kind", Value.Kind); IO.mapOptional("OverEmptyLines", Value.OverEmptyLines); } @@ -1651,6 +1652,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignTrailingComments = {}; LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; LLVMStyle.AlignTrailingComments.OverEmptyLines = 0; + LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true; LLVMStyle.AllowAllArgumentsOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never; diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 406c77c..fece384 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -1007,9 +1007,13 @@ void WhitespaceManager::alignTrailingComments() { return; const int Size = Changes.size(); + if (Size == 0) + return; + int MinColumn = 0; int StartOfSequence = 0; bool BreakBeforeNext = false; + bool IsInPP = Changes.front().Tok->Tok.is(tok::hash); int NewLineThreshold = 1; if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always) NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1; @@ -1018,7 +1022,19 @@ void WhitespaceManager::alignTrailingComments() { auto &C = Changes[I]; if (C.StartOfBlockComment) continue; - Newlines += C.NewlinesBefore; + if (C.NewlinesBefore != 0) { + Newlines += C.NewlinesBefore; + const bool WasInPP = std::exchange( + IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) || + C.ContinuesPPDirective); + if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) { + alignTrailingComments(StartOfSequence, I, MinColumn); + MinColumn = 0; + MaxColumn = INT_MAX; + StartOfSequence = I; + Newlines = 0; + } + } if (!C.IsTrailingComment) continue; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index d7d56b8..3595bbc 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -1233,20 +1233,6 @@ void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() { llvm::outs()); } -void GetDependenciesByModuleNameAction::ExecuteAction() { - CompilerInstance &CI = getCompilerInstance(); - Preprocessor &PP = CI.getPreprocessor(); - SourceManager &SM = PP.getSourceManager(); - FileID MainFileID = SM.getMainFileID(); - SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID); - SmallVector<IdentifierLoc, 2> Path; - IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName); - Path.emplace_back(FileStart, ModuleID); - auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false); - PPCallbacks *CB = PP.getPPCallbacks(); - CB->moduleImport(SourceLocation(), Path, ModResult); -} - //===----------------------------------------------------------------------===// // HLSL Specific Actions //===----------------------------------------------------------------------===// diff --git a/clang/lib/Headers/llvm_libc_wrappers/stdlib.h b/clang/lib/Headers/llvm_libc_wrappers/stdlib.h index 1da22abd0..d79e7fa 100644 --- a/clang/lib/Headers/llvm_libc_wrappers/stdlib.h +++ b/clang/lib/Headers/llvm_libc_wrappers/stdlib.h @@ -34,13 +34,13 @@ _Static_assert(__builtin_offsetof(div_t, quot) == 0, "ABI mismatch!"); _Static_assert(__builtin_offsetof(ldiv_t, quot) == 0, "ABI mismatch!"); _Static_assert(__builtin_offsetof(lldiv_t, quot) == 0, "ABI mismatch!"); -#if defined(__GLIBC__) && __cplusplus >= 201703L +#if defined(__GLIBC__) && __cplusplus >= 201103L #define at_quick_exit atexit #endif #include <llvm-libc-decls/stdlib.h> -#if defined(__GLIBC__) && __cplusplus >= 201703L +#if defined(__GLIBC__) && __cplusplus >= 201103L #undef at_quick_exit #endif diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 31bc941..334438e 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3178,6 +3178,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_align: case OMPC_message: case OMPC_ompx_dyn_cgroup_mem: + case OMPC_dyn_groupprivate: // OpenMP [2.5, Restrictions] // At most one num_threads clause can appear on the directive. // OpenMP [2.8.1, simd construct, Restrictions] @@ -3216,7 +3217,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) Clause = ParseOpenMPClause(CKind, WrongDirective); else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks || - CKind == OMPC_num_threads) + CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate) Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); else Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); @@ -4009,6 +4010,83 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, Arg.push_back(OMPC_GRAINSIZE_unknown); KLoc.emplace_back(); } + } else if (Kind == OMPC_dyn_groupprivate) { + enum { SimpleModifier, ComplexModifier, NumberOfModifiers }; + Arg.resize(NumberOfModifiers); + KLoc.resize(NumberOfModifiers); + Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown; + Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown; + + auto ConsumeModifier = [&]() { + unsigned Type = NumberOfModifiers; + unsigned Modifier; + SourceLocation Loc; + if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" && + NextToken().is(tok::l_paren)) { + ConsumeToken(); + BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren); + ParenT.consumeOpen(); + + Modifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); + if (Modifier <= OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown || + Modifier >= OMPC_DYN_GROUPPRIVATE_FALLBACK_last) { + Diag(Tok.getLocation(), diag::err_expected) + << "'abort', 'null' or 'default_mem' in fallback modifier"; + SkipUntil(tok::r_paren); + return std::make_tuple(Type, Modifier, Loc); + } + Type = ComplexModifier; + Loc = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + ParenT.consumeClose(); + } else { + Modifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); + if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) { + Type = SimpleModifier; + Loc = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + } + } + return std::make_tuple(Type, Modifier, Loc); + }; + + auto SaveModifier = [&](unsigned Type, unsigned Modifier, + SourceLocation Loc) { + assert(Type < NumberOfModifiers && "Unexpected modifier type"); + if (!KLoc[Type].isValid()) { + Arg[Type] = Modifier; + KLoc[Type] = Loc; + } else { + Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier) + << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier) + << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]); + } + }; + + // Parse 'modifier' + auto [Type1, Mod1, Loc1] = ConsumeModifier(); + if (Type1 < NumberOfModifiers) { + SaveModifier(Type1, Mod1, Loc1); + if (Tok.is(tok::comma)) { + // Parse ',' 'modifier' + ConsumeAnyToken(); + auto [Type2, Mod2, Loc2] = ConsumeModifier(); + if (Type2 < NumberOfModifiers) + SaveModifier(Type2, Mod2, Loc2); + } + // Parse ':' + if (Tok.is(tok::colon)) + ConsumeAnyToken(); + else + Diag(Tok, diag::warn_pragma_expected_colon) + << "dyn_groupprivate modifier"; + } } else if (Kind == OMPC_num_tasks) { // Parse optional <num_tasks modifier> ':' OpenMPNumTasksClauseModifier Modifier = @@ -4083,11 +4161,11 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, } } - bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || - (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || - Kind == OMPC_if || Kind == OMPC_device || - Kind == OMPC_grainsize || Kind == OMPC_num_tasks || - Kind == OMPC_num_threads; + bool NeedAnExpression = + (Kind == OMPC_schedule && DelimLoc.isValid()) || + (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if || + Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks || + Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate; if (NeedAnExpression) { SourceLocation ELoc = Tok.getLocation(); ExprResult LHS( diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 256f952..465dab2 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -16532,6 +16532,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, case OMPC_holds: Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_dyn_groupprivate: case OMPC_grainsize: case OMPC_num_tasks: case OMPC_num_threads: @@ -16658,6 +16659,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_num_teams: case OMPC_thread_limit: case OMPC_ompx_dyn_cgroup_mem: + case OMPC_dyn_groupprivate: + // TODO: This may need to consider teams too. if (Leafs[0] == OMPD_target) return OMPD_target; break; @@ -17705,7 +17708,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( SourceLocation EndLoc) { OMPClause *Res = nullptr; switch (Kind) { - case OMPC_schedule: + case OMPC_schedule: { enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; assert(Argument.size() == NumberOfElements && ArgumentLoc.size() == NumberOfElements); @@ -17716,6 +17719,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2], ArgumentLoc[ScheduleKind], DelimLoc, EndLoc); break; + } case OMPC_if: assert(Argument.size() == 1 && ArgumentLoc.size() == 1); Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()), @@ -17771,6 +17775,20 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr, StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); break; + case OMPC_dyn_groupprivate: { + enum { Modifier1, Modifier2, NumberOfElements }; + assert(Argument.size() == NumberOfElements && + ArgumentLoc.size() == NumberOfElements && + "Modifiers for dyn_groupprivate clause and their locations are " + "expected."); + Res = ActOnOpenMPDynGroupprivateClause( + static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]), + static_cast<OpenMPDynGroupprivateClauseFallbackModifier>( + Argument[Modifier2]), + Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1], + ArgumentLoc[Modifier2], EndLoc); + break; + } case OMPC_num_threads: assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && "Modifier for num_threads clause and its location are expected."); @@ -18127,6 +18145,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_affinity: case OMPC_when: case OMPC_ompx_dyn_cgroup_mem: + case OMPC_dyn_groupprivate: default: llvm_unreachable("Clause is not allowed."); } @@ -25246,6 +25265,49 @@ OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size, ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); } +OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause( + OpenMPDynGroupprivateClauseModifier M1, + OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, + SourceLocation M2Loc, SourceLocation EndLoc) { + + if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) || + (M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) { + std::string Values = getListOfPossibleValues( + OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown); + Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc + : M2Loc, + diag::err_omp_unexpected_clause_value) + << Values << getOpenMPClauseName(OMPC_dyn_groupprivate); + return nullptr; + } + + Expr *ValExpr = Size; + Stmt *HelperValStmt = nullptr; + + // OpenMP [2.5, Restrictions] + // The dyn_groupprivate expression must evaluate to a positive integer + // value. + if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate, + /*StrictlyPositive=*/false)) + return nullptr; + + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( + DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP); + if (CaptureRegion != OMPD_unknown && + !SemaRef.CurContext->isDependentContext()) { + ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); + llvm::MapVector<const Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(getASTContext(), Captures); + } + + return new (getASTContext()) OMPDynGroupprivateClause( + StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1, + M1Loc, M2, M2Loc); +} + OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause( OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 94105f1..c249148 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2463,6 +2463,19 @@ public: LParenLoc, EndLoc); } + /// Build a new OpenMP 'dyn_groupprivate' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPDynGroupprivateClause( + OpenMPDynGroupprivateClauseModifier M1, + OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, + SourceLocation M2Loc, SourceLocation EndLoc) { + return getSema().OpenMP().ActOnOpenMPDynGroupprivateClause( + M1, M2, Size, StartLoc, LParenLoc, M1Loc, M2Loc, EndLoc); + } + /// Build a new OpenMP 'ompx_attribute' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -11726,6 +11739,19 @@ OMPClause *TreeTransform<Derived>::TransformOMPXDynCGroupMemClause( } template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPDynGroupprivateClause( + OMPDynGroupprivateClause *C) { + ExprResult Size = getDerived().TransformExpr(C->getSize()); + if (Size.isInvalid()) + return nullptr; + return getDerived().RebuildOMPDynGroupprivateClause( + C->getDynGroupprivateModifier(), C->getDynGroupprivateFallbackModifier(), + Size.get(), C->getBeginLoc(), C->getLParenLoc(), + C->getDynGroupprivateModifierLoc(), + C->getDynGroupprivateFallbackModifierLoc(), C->getEndLoc()); +} + +template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPDoacrossClause(OMPDoacrossClause *C) { llvm::SmallVector<Expr *, 16> Vars; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index d552821..a04041c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11544,6 +11544,9 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_ompx_dyn_cgroup_mem: C = new (Context) OMPXDynCGroupMemClause(); break; + case llvm::omp::OMPC_dyn_groupprivate: + C = new (Context) OMPDynGroupprivateClause(); + break; case llvm::omp::OMPC_doacross: { unsigned NumVars = Record.readInt(); unsigned NumLoops = Record.readInt(); @@ -12736,6 +12739,19 @@ void OMPClauseReader::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { C->setLParenLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPDynGroupprivateClause( + OMPDynGroupprivateClause *C) { + VisitOMPClauseWithPreInit(C); + C->setDynGroupprivateModifier( + Record.readEnum<OpenMPDynGroupprivateClauseModifier>()); + C->setDynGroupprivateFallbackModifier( + Record.readEnum<OpenMPDynGroupprivateClauseFallbackModifier>()); + C->setSize(Record.readSubExpr()); + C->setLParenLoc(Record.readSourceLocation()); + C->setDynGroupprivateModifierLoc(Record.readSourceLocation()); + C->setDynGroupprivateFallbackModifierLoc(Record.readSourceLocation()); +} + void OMPClauseReader::VisitOMPDoacrossClause(OMPDoacrossClause *C) { C->setLParenLoc(Record.readSourceLocation()); C->setDependenceType( diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index b1fd151..821e7df 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -8651,6 +8651,17 @@ void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { Record.AddSourceLocation(C->getLParenLoc()); } +void OMPClauseWriter::VisitOMPDynGroupprivateClause( + OMPDynGroupprivateClause *C) { + VisitOMPClauseWithPreInit(C); + Record.push_back(C->getDynGroupprivateModifier()); + Record.push_back(C->getDynGroupprivateFallbackModifier()); + Record.AddStmt(C->getSize()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getDynGroupprivateModifierLoc()); + Record.AddSourceLocation(C->getDynGroupprivateFallbackModifierLoc()); +} + void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) { Record.push_back(C->varlist_size()); Record.push_back(C->getNumLoops()); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp index eebecdb..33f5640 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp @@ -1,4 +1,4 @@ -//===- DependencyScanner.cpp - Performs module dependency scanning --------===// +//===- DependencyScannerImpl.cpp - Implements module dependency scanning --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,6 +12,7 @@ #include "clang/Driver/Driver.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/TargetParser/Host.h" using namespace clang; @@ -456,7 +457,8 @@ initVFSForTUBuferScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, return std::make_pair(ModifiedFS, ModifiedCommandLine); } -std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>> +std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, + std::vector<std::string>> initVFSForByNameScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, ArrayRef<std::string> CommandLine, StringRef WorkingDirectory, StringRef ModuleName) { @@ -588,7 +590,7 @@ computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, } std::unique_ptr<DependencyOutputOptions> -takeDependencyOutputOptionsFrom(CompilerInstance &ScanInstance) { +takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance) { // This function moves the existing dependency output options from the // invocation to the collector. The options in the invocation are reset, // which ensures that the compiler won't create new dependency collectors, @@ -675,7 +677,7 @@ bool DependencyScanningAction::runInvocation( if (!MaybePrebuiltModulesASTMap) return false; - auto DepOutputOpts = takeDependencyOutputOptionsFrom(ScanInstance); + auto DepOutputOpts = takeAndUpdateDependencyOutputOptionsFrom(ScanInstance); MDC = initializeScanInstanceDependencyCollector( ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer, @@ -686,8 +688,6 @@ bool DependencyScanningAction::runInvocation( if (Service.getFormat() == ScanningOutputFormat::P1689) Action = std::make_unique<PreprocessOnlyAction>(); - else if (ModuleName) - Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName); else Action = std::make_unique<ReadPCHAndPreprocessAction>(); @@ -704,3 +704,175 @@ bool DependencyScanningAction::runInvocation( return Result; } + +bool CompilerInstanceWithContext::initialize(DiagnosticConsumer *DC) { + if (DC) { + DiagConsumer = DC; + } else { + DiagPrinterWithOS = + std::make_unique<TextDiagnosticsPrinterWithOutput>(CommandLine); + DiagConsumer = &DiagPrinterWithOS->DiagPrinter; + } + + DiagEngineWithCmdAndOpts = std::make_unique<DignosticsEngineWithDiagOpts>( + CommandLine, OverlayFS, *DiagConsumer); + + std::tie(OverlayFS, CommandLine) = initVFSForByNameScanning( + Worker.BaseFS, CommandLine, CWD, "ScanningByName"); + + std::tie(Driver, Compilation) = buildCompilation( + CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS, Alloc); + + if (!Compilation) + return false; + + assert(Compilation->getJobs().size() && + "Must have a job list of non-zero size"); + const driver::Command &Command = *(Compilation->getJobs().begin()); + const auto &CommandArgs = Command.getArguments(); + assert(!CommandArgs.empty() && "Cannot have a command with 0 args"); + assert(StringRef(CommandArgs[0]) == "-cc1" && "Requires a cc1 job."); + OriginalInvocation = std::make_unique<CompilerInvocation>(); + + if (!CompilerInvocation::CreateFromArgs(*OriginalInvocation, CommandArgs, + *DiagEngineWithCmdAndOpts->DiagEngine, + Command.getExecutable())) { + DiagEngineWithCmdAndOpts->DiagEngine->Report( + diag::err_fe_expected_compiler_job) + << llvm::join(CommandLine, " "); + return false; + } + + if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros)) + canonicalizeDefines(OriginalInvocation->getPreprocessorOpts()); + + // Create the CompilerInstance. + IntrusiveRefCntPtr<ModuleCache> ModCache = + makeInProcessModuleCache(Worker.Service.getModuleCacheEntries()); + CIPtr = std::make_unique<CompilerInstance>( + std::make_shared<CompilerInvocation>(*OriginalInvocation), + Worker.PCHContainerOps, ModCache.get()); + auto &CI = *CIPtr; + + if (!initializeScanCompilerInstance( + CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(), + Worker.Service, Worker.DepFS)) + return false; + + StableDirs = getInitialStableDirs(CI); + auto MaybePrebuiltModulesASTMap = + computePrebuiltModulesASTMap(CI, StableDirs); + if (!MaybePrebuiltModulesASTMap) + return false; + + PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap); + OutputOpts = takeAndUpdateDependencyOutputOptionsFrom(CI); + + // We do not create the target in initializeScanCompilerInstance because + // setting it here is unique for by-name lookups. We create the target only + // once here, and the information is reused for all computeDependencies calls. + // We do not need to call createTarget explicitly if we go through + // CompilerInstance::ExecuteAction to perform scanning. + CI.createTarget(); + + return true; +} + +bool CompilerInstanceWithContext::computeDependencies( + StringRef ModuleName, DependencyConsumer &Consumer, + DependencyActionController &Controller) { + assert(CIPtr && "CIPtr must be initialized before calling this method"); + auto &CI = *CIPtr; + + // We create this cleanup object because computeDependencies may exit + // early with errors. + auto CleanUp = llvm::make_scope_exit([&]() { + CI.clearDependencyCollectors(); + // The preprocessor may not be created at the entry of this method, + // but it must have been created when this method returns, whether + // there are errors during scanning or not. + CI.getPreprocessor().removePPCallbacks(); + }); + + auto MDC = initializeScanInstanceDependencyCollector( + CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), CWD, Consumer, + Worker.Service, + /* The MDC's constructor makes a copy of the OriginalInvocation, so + we can pass it in without worrying that it might be changed across + invocations of computeDependencies. */ + *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs); + + if (!SrcLocOffset) { + // When SrcLocOffset is zero, we are at the beginning of the fake source + // file. In this case, we call BeginSourceFile to initialize. + std::unique_ptr<FrontendAction> Action = + std::make_unique<PreprocessOnlyAction>(); + auto InputFile = CI.getFrontendOpts().Inputs.begin(); + bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile); + assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed"); + (void)ActionBeginSucceeded; + } + + Preprocessor &PP = CI.getPreprocessor(); + SourceManager &SM = PP.getSourceManager(); + FileID MainFileID = SM.getMainFileID(); + SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID); + SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset); + PPCallbacks *CB = nullptr; + if (!SrcLocOffset) { + // We need to call EnterSourceFile when SrcLocOffset is zero to initialize + // the preprocessor. + bool PPFailed = PP.EnterSourceFile(MainFileID, nullptr, SourceLocation()); + assert(!PPFailed && "Preprocess must be able to enter the main file."); + (void)PPFailed; + CB = MDC->getPPCallbacks(); + } else { + // When SrcLocOffset is non-zero, the preprocessor has already been + // initialized through a previous call of computeDependencies. We want to + // preserve the PP's state, hence we do not call EnterSourceFile again. + MDC->attachToPreprocessor(PP); + CB = MDC->getPPCallbacks(); + + FileID PrevFID; + SrcMgr::CharacteristicKind FileType = SM.getFileCharacteristic(IDLocation); + CB->LexedFileChanged(MainFileID, + PPChainedCallbacks::LexedFileChangeReason::EnterFile, + FileType, PrevFID, IDLocation); + } + + SrcLocOffset++; + SmallVector<IdentifierLoc, 2> Path; + IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName); + Path.emplace_back(IDLocation, ModuleID); + auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false); + + assert(CB && "Must have PPCallbacks after module loading"); + CB->moduleImport(SourceLocation(), Path, ModResult); + // Note that we are calling the CB's EndOfMainFile function, which + // forwards the results to the dependency consumer. + // It does not indicate the end of processing the fake file. + CB->EndOfMainFile(); + + if (!ModResult) + return false; + + CompilerInvocation ModuleInvocation(*OriginalInvocation); + MDC->applyDiscoveredDependencies(ModuleInvocation); + Consumer.handleBuildCommand( + {CommandLine[0], ModuleInvocation.getCC1CommandLine()}); + + return true; +} + +bool CompilerInstanceWithContext::finalize() { + DiagConsumer->finish(); + return true; +} + +llvm::Error CompilerInstanceWithContext::handleReturnStatus(bool Success) { + assert(DiagPrinterWithOS && "Must use the default DiagnosticConsumer."); + return Success ? llvm::Error::success() + : llvm::make_error<llvm::StringError>( + DiagPrinterWithOS->DiagnosticsOS.str(), + llvm::inconvertibleErrorCode()); +} diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h index 5657317..54166da 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h @@ -1,4 +1,4 @@ -//===- DependencyScanner.h - Performs module dependency scanning *- C++ -*-===// +//===- DependencyScannerImpl.h - Implements dependency scanning *- C++ -*--===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -23,6 +23,8 @@ class DiagnosticConsumer; namespace tooling { namespace dependencies { class DependencyScanningService; +class DependencyScanningWorker; + class DependencyConsumer; class DependencyActionController; class DependencyScanningWorkerFilesystem; @@ -35,8 +37,7 @@ public: IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS, std::optional<StringRef> ModuleName = std::nullopt) : Service(Service), WorkingDirectory(WorkingDirectory), - Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)), - ModuleName(ModuleName) {} + Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)) {} bool runInvocation(std::unique_ptr<CompilerInvocation> Invocation, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, std::shared_ptr<PCHContainerOperations> PCHContainerOps, @@ -66,7 +67,6 @@ private: DependencyConsumer &Consumer; DependencyActionController &Controller; IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS; - std::optional<StringRef> ModuleName; std::optional<CompilerInstance> ScanInstanceStorage; std::shared_ptr<ModuleDepCollector> MDC; std::vector<std::string> LastCC1Arguments; @@ -118,7 +118,8 @@ initVFSForTUBuferScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, StringRef WorkingDirectory, llvm::MemoryBufferRef TUBuffer); -std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>> +std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, + std::vector<std::string>> initVFSForByNameScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, ArrayRef<std::string> CommandLine, StringRef WorkingDirectory, StringRef ModuleName); @@ -137,7 +138,7 @@ computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, SmallVector<StringRef> &StableDirs); std::unique_ptr<DependencyOutputOptions> -takeDependencyOutputOptionsFrom(CompilerInstance &ScanInstance); +takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance); /// Create the dependency collector that will collect the produced /// dependencies. May return the created ModuleDepCollector depending @@ -150,6 +151,60 @@ std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector( DependencyActionController &Controller, PrebuiltModulesAttrsMap PrebuiltModulesASTMap, llvm::SmallVector<StringRef> &StableDirs); + +class CompilerInstanceWithContext { + // Context + DependencyScanningWorker &Worker; + llvm::StringRef CWD; + std::vector<std::string> CommandLine; + + // Context - file systems + llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS; + + // Context - Diagnostics engine. + std::unique_ptr<TextDiagnosticsPrinterWithOutput> DiagPrinterWithOS; + // DiagConsumer may points to DiagPrinterWithOS->DiagPrinter, or a custom + // DiagnosticConsumer passed in from initialize. + DiagnosticConsumer *DiagConsumer = nullptr; + std::unique_ptr<DignosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts; + + // Context - compiler invocation + // Compilation's command's arguments may be owned by Alloc when expanded from + // response files, so we need to keep Alloc alive in the context. + llvm::BumpPtrAllocator Alloc; + std::unique_ptr<clang::driver::Driver> Driver; + std::unique_ptr<clang::driver::Compilation> Compilation; + std::unique_ptr<CompilerInvocation> OriginalInvocation; + + // Context - output options + std::unique_ptr<DependencyOutputOptions> OutputOpts; + + // Context - stable directory handling + llvm::SmallVector<StringRef> StableDirs; + PrebuiltModulesAttrsMap PrebuiltModuleASTMap; + + // Compiler Instance + std::unique_ptr<CompilerInstance> CIPtr; + + // Source location offset. + int32_t SrcLocOffset = 0; + +public: + CompilerInstanceWithContext(DependencyScanningWorker &Worker, StringRef CWD, + const std::vector<std::string> &CMD) + : Worker(Worker), CWD(CWD), CommandLine(CMD) {}; + + // The three methods below returns false when they fail, with the detail + // accumulated in DiagConsumer. + bool initialize(DiagnosticConsumer *DC); + bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer, + DependencyActionController &Controller); + bool finalize(); + + // The method below turns the return status from the above methods + // into an llvm::Error using a default DiagnosticConsumer. + llvm::Error handleReturnStatus(bool Success); +}; } // namespace dependencies } // namespace tooling } // namespace clang diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp index 27734ff..a1f2db7 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp @@ -162,13 +162,45 @@ DependencyScanningTool::getModuleDependencies( LookupModuleOutputCallback LookupModuleOutput) { FullDependencyConsumer Consumer(AlreadySeen); CallbackActionController Controller(LookupModuleOutput); - llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer, - Controller, ModuleName); + if (auto Error = + Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine)) + return std::move(Error); + + auto Result = Worker.computeDependenciesByNameWithContextOrError( + ModuleName, Consumer, Controller); + + if (auto Error = Worker.finalizeCompilerInstanceWithContextOrError()) + return std::move(Error); + if (Result) return std::move(Result); + return Consumer.takeTranslationUnitDeps(); } +llvm::Error DependencyScanningTool::initializeCompilerInstanceWithContext( + StringRef CWD, const std::vector<std::string> &CommandLine) { + return Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine); +} + +llvm::Expected<TranslationUnitDeps> +DependencyScanningTool::computeDependenciesByNameWithContext( + StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen, + LookupModuleOutputCallback LookupModuleOutput) { + FullDependencyConsumer Consumer(AlreadySeen); + CallbackActionController Controller(LookupModuleOutput); + llvm::Error Result = Worker.computeDependenciesByNameWithContextOrError( + ModuleName, Consumer, Controller); + if (Result) + return std::move(Result); + + return Consumer.takeTranslationUnitDeps(); +} + +llvm::Error DependencyScanningTool::finalizeCompilerInstanceWithContext() { + return Worker.finalizeCompilerInstanceWithContextOrError(); +} + TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() { TranslationUnitDeps TU; diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 0a1cf6b..dc408b1 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -43,6 +43,9 @@ DependencyScanningWorker::DependencyScanningWorker( } } +DependencyScanningWorker::~DependencyScanningWorker() = default; +DependencyActionController::~DependencyActionController() = default; + llvm::Error DependencyScanningWorker::computeDependencies( StringRef WorkingDirectory, const std::vector<std::string> &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, @@ -58,21 +61,6 @@ llvm::Error DependencyScanningWorker::computeDependencies( DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode()); } -llvm::Error DependencyScanningWorker::computeDependencies( - StringRef WorkingDirectory, const std::vector<std::string> &CommandLine, - DependencyConsumer &Consumer, DependencyActionController &Controller, - StringRef ModuleName) { - // Capture the emitted diagnostics and report them to the client - // in the case of a failure. - TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine); - - if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller, - DiagPrinterWithOS.DiagPrinter, ModuleName)) - return llvm::Error::success(); - return llvm::make_error<llvm::StringError>( - DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode()); -} - static bool forEachDriverJob( ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, @@ -113,11 +101,11 @@ static bool createAndRunToolInvocation( bool DependencyScanningWorker::scanDependencies( StringRef WorkingDirectory, const std::vector<std::string> &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, - DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, - std::optional<StringRef> ModuleName) { + DiagnosticConsumer &DC, + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { DignosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC); DependencyScanningAction Action(Service, WorkingDirectory, Consumer, - Controller, DepFS, ModuleName); + Controller, DepFS); bool Success = false; if (CommandLine[1] == "-cc1") { @@ -172,24 +160,51 @@ bool DependencyScanningWorker::computeDependencies( auto [FinalFS, FinalCommandLine] = initVFSForTUBuferScanning( BaseFS, CommandLine, WorkingDirectory, *TUBuffer); return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer, - Controller, DC, FinalFS, - /*ModuleName=*/std::nullopt); + Controller, DC, FinalFS); } else { BaseFS->setCurrentWorkingDirectory(WorkingDirectory); return scanDependencies(WorkingDirectory, CommandLine, Consumer, Controller, - DC, BaseFS, /*ModuleName=*/std::nullopt); + DC, BaseFS); } } -bool DependencyScanningWorker::computeDependencies( - StringRef WorkingDirectory, const std::vector<std::string> &CommandLine, - DependencyConsumer &Consumer, DependencyActionController &Controller, - DiagnosticConsumer &DC, StringRef ModuleName) { - auto [OverlayFS, ModifiedCommandLine] = initVFSForByNameScanning( - BaseFS, CommandLine, WorkingDirectory, ModuleName); +llvm::Error +DependencyScanningWorker::initializeCompilerInstanceWithContextOrError( + StringRef CWD, const std::vector<std::string> &CommandLine) { + bool Success = initializeCompilerInstanceWithContext(CWD, CommandLine); + return CIWithContext->handleReturnStatus(Success); +} + +llvm::Error +DependencyScanningWorker::computeDependenciesByNameWithContextOrError( + StringRef ModuleName, DependencyConsumer &Consumer, + DependencyActionController &Controller) { + bool Success = + computeDependenciesByNameWithContext(ModuleName, Consumer, Controller); + return CIWithContext->handleReturnStatus(Success); +} + +llvm::Error +DependencyScanningWorker::finalizeCompilerInstanceWithContextOrError() { + bool Success = finalizeCompilerInstance(); + return CIWithContext->handleReturnStatus(Success); +} - return scanDependencies(WorkingDirectory, ModifiedCommandLine, Consumer, - Controller, DC, OverlayFS, ModuleName); +bool DependencyScanningWorker::initializeCompilerInstanceWithContext( + StringRef CWD, const std::vector<std::string> &CommandLine, + DiagnosticConsumer *DC) { + CIWithContext = + std::make_unique<CompilerInstanceWithContext>(*this, CWD, CommandLine); + return CIWithContext->initialize(DC); } -DependencyActionController::~DependencyActionController() {} +bool DependencyScanningWorker::computeDependenciesByNameWithContext( + StringRef ModuleName, DependencyConsumer &Consumer, + DependencyActionController &Controller) { + assert(CIWithContext && "CompilerInstance with context required!"); + return CIWithContext->computeDependencies(ModuleName, Consumer, Controller); +} + +bool DependencyScanningWorker::finalizeCompilerInstance() { + return CIWithContext->finalize(); +} diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index a117bec..e07a208 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -965,7 +965,9 @@ ModuleDepCollector::ModuleDepCollector( makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {} void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) { - PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(*this)); + auto CollectorPP = std::make_unique<ModuleDepCollectorPP>(*this); + CollectorPPPtr = CollectorPP.get(); + PP.addPPCallbacks(std::move(CollectorPP)); } void ModuleDepCollector::attachToASTReader(ASTReader &R) {} diff --git a/clang/test/CIR/CodeGen/statement-exprs.c b/clang/test/CIR/CodeGen/statement-exprs.c index c784ec9..2d05fc1 100644 --- a/clang/test/CIR/CodeGen/statement-exprs.c +++ b/clang/test/CIR/CodeGen/statement-exprs.c @@ -6,7 +6,7 @@ // RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG int f19(void) { - return ({ 3;;4;; }); + return ({ 3;;4; }); } // CIR: cir.func dso_local @f19() -> !s32i @@ -42,6 +42,16 @@ int f19(void) { // OGCG: %[[TMP_VAL:.+]] = load i32, ptr %[[TMP]] // OGCG: ret i32 %[[TMP_VAL]] +// PR166036: The trailing NullStmt should result in a void. +void f20(void) { + return ({ 3;;4;; }); +} + +// CIR-LABEL: cir.func dso_local @f20() {{[^-]*}} +// CIR: cir.return {{[^%]*}} + +// LLVM-LABEL: define{{.*}} void @f20 +// LLVM: ret void int nested(void) { ({123;}); diff --git a/clang/test/ClangScanDeps/link-libraries.c b/clang/test/ClangScanDeps/link-libraries.c index cc2e223..3719d71 100644 --- a/clang/test/ClangScanDeps/link-libraries.c +++ b/clang/test/ClangScanDeps/link-libraries.c @@ -32,7 +32,7 @@ module transitive { }] // RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json -// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=root > %t/result.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-names=root > %t/result.json // RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s // CHECK: { diff --git a/clang/test/ClangScanDeps/modules-full-by-mod-name.c b/clang/test/ClangScanDeps/modules-full-by-mod-name.c index c838614..edb9963 100644 --- a/clang/test/ClangScanDeps/modules-full-by-mod-name.c +++ b/clang/test/ClangScanDeps/modules-full-by-mod-name.c @@ -25,7 +25,7 @@ module transitive { header "transitive.h" } }] // RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json -// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=root > %t/result.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-names=root > %t/result.json // RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s // CHECK: { diff --git a/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c b/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c new file mode 100644 index 0000000..030f7f3 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c @@ -0,0 +1,108 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +//--- module.modulemap +module root { header "root.h" } +module direct { header "direct.h" } +module transitive { header "transitive.h" } +module root1 { header "root1.h"} +//--- root.h +#include "direct.h" +#include "root/textual.h" + +//--- root1.h +#include "direct.h" + +//--- direct.h +#include "transitive.h" +//--- transitive.h +// empty + +//--- root/textual.h +// This is here to verify that the "root" directory doesn't clash with name of +// the "root" module. + +//--- cdb.json.template +[{ + "file": "", + "directory": "DIR", + "command": "clang -fmodules -fmodules-cache-path=DIR/cache -I DIR -x c" +}] + +// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-names=root,root1,direct > %t/result.json +// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s + +// CHECK: { +// CHECK-NEXT: "modules": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "module-name": "transitive" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK: ], +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "[[PREFIX]]/direct.h" +// CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], +// CHECK-NEXT: "name": "direct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "module-name": "direct" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK: ], +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "[[PREFIX]]/root.h", +// CHECK-NEXT: "[[PREFIX]]/root/textual.h" +// CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], +// CHECK-NEXT: "name": "root" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "module-name": "direct" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK: ], +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "[[PREFIX]]/root1.h" +// CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], +// CHECK-NEXT: "name": "root1" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK: ], +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "[[PREFIX]]/transitive.h" +// CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], +// CHECK-NEXT: "name": "transitive" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "translation-units": [] +// CHECK-NEXT: } diff --git a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c index 670b650..929df94 100644 --- a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c @@ -26,16 +26,36 @@ int32_t test_vcvtas_s32_f32(float32_t a) { return (int32_t)vcvtas_s32_f32(a); } -// CHECK-LABEL: define {{[^@]+}}@test_test_vcvtad_s64_f64 +// CHECK-LABEL: define {{[^@]+}}@test_vcvtad_s64_f64 // CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[VCVTAD_S64_F64_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtas.i64.f64(double [[A]]) // CHECK-NEXT: ret i64 [[VCVTAD_S64_F64_I]] // -int64_t test_test_vcvtad_s64_f64(float64_t a) { +int64_t test_vcvtad_s64_f64(float64_t a) { return (int64_t)vcvtad_s64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtas_s64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTAS_S64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtas.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTAS_S64_F32_I]] +// +int64_t test_vcvtas_s64_f32(float32_t a) { + return (int64_t)vcvtas_s64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtad_s32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTAD_S32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtas.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTAD_S32_F64_I]] +// +int32_t test_vcvtad_s32_f64(float64_t a) { + return (int32_t)vcvtad_s32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtas_u32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -56,6 +76,26 @@ uint64_t test_vcvtad_u64_f64(float64_t a) { return (uint64_t)vcvtad_u64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtas_u64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTAS_U64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtau.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTAS_U64_F32_I]] +// +uint64_t test_vcvtas_u64_f32(float32_t a) { + return (uint64_t)vcvtas_u64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtad_u32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTAD_U32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtau.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTAD_U32_F64_I]] +// +uint32_t test_vcvtad_u32_f64(float64_t a) { + return (uint32_t)vcvtad_u32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtms_s32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -76,6 +116,26 @@ int64_t test_vcvtmd_s64_f64(float64_t a) { return (int64_t)vcvtmd_s64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtms_s64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTMS_S64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtms.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTMS_S64_F32_I]] +// +int64_t test_vcvtms_s64_f32(float32_t a) { + return (int64_t)vcvtms_s64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtmd_s32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTMD_S32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtms.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTMD_S32_F64_I]] +// +int32_t test_vcvtmd_s32_f64(float64_t a) { + return (int32_t)vcvtmd_s32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtms_u32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -96,6 +156,26 @@ uint64_t test_vcvtmd_u64_f64(float64_t a) { return (uint64_t)vcvtmd_u64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtms_u64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTMS_U64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtmu.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTMS_U64_F32_I]] +// +uint64_t test_vcvtms_u64_f32(float32_t a) { + return (uint64_t)vcvtms_u64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtmd_u32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTMD_U32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtmu.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTMD_U32_F64_I]] +// +uint32_t test_vcvtmd_u32_f64(float64_t a) { + return (uint32_t)vcvtmd_u32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtns_s32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -116,6 +196,26 @@ int64_t test_vcvtnd_s64_f64(float64_t a) { return (int64_t)vcvtnd_s64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtns_s64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTNS_S64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtns.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTNS_S64_F32_I]] +// +int64_t test_vcvtns_s64_f32(float32_t a) { + return (int64_t)vcvtns_s64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtnd_s32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTND_S32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtns.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTND_S32_F64_I]] +// +int32_t test_vcvtnd_s32_f64(float64_t a) { + return (int32_t)vcvtnd_s32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtns_u32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -136,6 +236,26 @@ uint64_t test_vcvtnd_u64_f64(float64_t a) { return (uint64_t)vcvtnd_u64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtns_u64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTNS_U64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtnu.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTNS_U64_F32_I]] +// +uint64_t test_vcvtns_u64_f32(float32_t a) { + return (uint64_t)vcvtns_u64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtnd_u32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTND_U32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtnu.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTND_U32_F64_I]] +// +uint32_t test_vcvtnd_u32_f64(float64_t a) { + return (uint32_t)vcvtnd_u32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtps_s32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -156,6 +276,26 @@ int64_t test_vcvtpd_s64_f64(float64_t a) { return (int64_t)vcvtpd_s64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtps_s64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTPS_S64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtps.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTPS_S64_F32_I]] +// +int64_t test_vcvtps_s64_f32(float32_t a) { + return (int64_t)vcvtps_s64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtpd_s32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTPD_S32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtps.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTPD_S32_F64_I]] +// +int32_t test_vcvtpd_s32_f64(float64_t a) { + return (int32_t)vcvtpd_s32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvtps_u32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -176,6 +316,26 @@ uint64_t test_vcvtpd_u64_f64(float64_t a) { return (uint64_t)vcvtpd_u64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvtps_u64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTPS_U64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtpu.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTPS_U64_F32_I]] +// +uint64_t test_vcvtps_u64_f32(float32_t a) { + return (uint64_t)vcvtps_u64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtpd_u32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTPD_U32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtpu.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTPD_U32_F64_I]] +// +uint32_t test_vcvtpd_u32_f64(float64_t a) { + return (uint32_t)vcvtpd_u32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvts_s32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -196,6 +356,26 @@ int64_t test_vcvtd_s64_f64(float64_t a) { return (int64_t)vcvtd_s64_f64(a); } +// CHECK-LABEL: define {{[^@]+}}@test_vcvts_s64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTS_S64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtzs.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTS_S64_F32_I]] +// +int64_t test_vcvts_s64_f32(float32_t a) { + return (int64_t)vcvts_s64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtd_s32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTD_S32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtzs.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTD_S32_F64_I]] +// +int32_t test_vcvtd_s32_f64(float64_t a) { + return (int32_t)vcvtd_s32_f64(a); +} + // CHECK-LABEL: define {{[^@]+}}@test_vcvts_u32_f32 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -215,3 +395,24 @@ uint32_t test_vcvts_u32_f32(float32_t a) { uint64_t test_vcvtd_u64_f64(float64_t a) { return (uint64_t)vcvtd_u64_f64(a); } + +// CHECK-LABEL: define {{[^@]+}}@test_vcvts_u64_f32 +// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTS_U64_F32_I:%.*]] = call i64 @llvm.aarch64.neon.fcvtzu.i64.f32(float [[A]]) +// CHECK-NEXT: ret i64 [[VCVTS_U64_F32_I]] +// +uint64_t test_vcvts_u64_f32(float32_t a) { + return (uint64_t)vcvts_u64_f32(a); +} + +// CHECK-LABEL: define {{[^@]+}}@test_vcvtd_u32_f64 +// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VCVTD_U32_F64_I:%.*]] = call i32 @llvm.aarch64.neon.fcvtzu.i32.f64(double [[A]]) +// CHECK-NEXT: ret i32 [[VCVTD_U32_F64_I]] +// +uint32_t test_vcvtd_u32_f64(float64_t a) { + return (uint32_t)vcvtd_u32_f64(a); +} + diff --git a/clang/test/CodeGen/AArch64/v9.6a-neon-f16-intrinsics.c b/clang/test/CodeGen/AArch64/v9.6a-neon-f16-intrinsics.c new file mode 100644 index 0000000..89ee9e3 --- /dev/null +++ b/clang/test/CodeGen/AArch64/v9.6a-neon-f16-intrinsics.c @@ -0,0 +1,23 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -target-feature +v9.6a -target-feature +f8f16mm -target-feature +fp8 \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,sroa \ +// RUN: | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include <arm_neon.h> + +// CHECK-LABEL: define dso_local <8 x half> @test_vmmlaq_f16_mf8( +// CHECK-SAME: <8 x half> noundef [[P0:%.*]], <16 x i8> [[P1:%.*]], <16 x i8> [[P2:%.*]], i64 noundef [[P3:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x half> [[P0]] to <8 x i16> +// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[TMP0]] to <16 x i8> +// CHECK-NEXT: call void @llvm.aarch64.set.fpmr(i64 [[P3]]) +// CHECK-NEXT: [[FMMLA_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half> +// CHECK-NEXT: [[FMMLA1_I:%.*]] = call <8 x half> @llvm.aarch64.neon.fmmla.v8f16.v16i8(<8 x half> [[FMMLA_I]], <16 x i8> [[P1]], <16 x i8> [[P2]]) +// CHECK-NEXT: ret <8 x half> [[FMMLA1_I]] +// +float16x8_t test_vmmlaq_f16_mf8(float16x8_t p0, mfloat8x16_t p1, mfloat8x16_t p2, fpm_t p3) { + return vmmlaq_f16_mf8_fpm(p0, p1, p2, p3); +} diff --git a/clang/test/CodeGen/AArch64/v9.6a-neon-f32-intrinsics.c b/clang/test/CodeGen/AArch64/v9.6a-neon-f32-intrinsics.c new file mode 100644 index 0000000..13db72c --- /dev/null +++ b/clang/test/CodeGen/AArch64/v9.6a-neon-f32-intrinsics.c @@ -0,0 +1,21 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -target-feature +v9.6a -target-feature +f8f32mm -target-feature +fp8 \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,sroa \ +// RUN: | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include <arm_neon.h> + +// CHECK-LABEL: define dso_local <4 x float> @test_vmmlaq_f32_mf8( +// CHECK-SAME: <4 x float> noundef [[P0:%.*]], <16 x i8> [[P1:%.*]], <16 x i8> [[P2:%.*]], i64 noundef [[P3:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: call void @llvm.aarch64.set.fpmr(i64 [[P3]]) +// CHECK-NEXT: [[FMMLA_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmmla.v4f32.v16i8(<4 x float> [[P0]], <16 x i8> [[P1]], <16 x i8> [[P2]]) +// CHECK-NEXT: ret <4 x float> [[FMMLA_I]] +// +float32x4_t test_vmmlaq_f32_mf8(float32x4_t p0, mfloat8x16_t p1, mfloat8x16_t p2, fpm_t p3) { + return vmmlaq_f32_mf8_fpm(p0, p1, p2, p3); +} + diff --git a/clang/test/Modules/transitive-system.test b/clang/test/Modules/transitive-system.test index b1f1558..5f6196c 100644 --- a/clang/test/Modules/transitive-system.test +++ b/clang/test/Modules/transitive-system.test @@ -2,9 +2,9 @@ // RUN: split-file %s %t // RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json -// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=direct > %t/result1.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-names=direct > %t/result1.json // RUN: rm -rf %t/cache -// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=transitive > %t/result2.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-names=transitive > %t/result2.json // RUN: %deps-to-rsp %t/result1.json --module-name transitive > %t/1.rsp // RUN: %deps-to-rsp %t/result2.json --module-name transitive > %t/2.rsp // RUN: diff %t/1.rsp %t/2.rsp diff --git a/clang/test/OpenMP/target_dyn_groupprivate_messages.cpp b/clang/test/OpenMP/target_dyn_groupprivate_messages.cpp new file mode 100644 index 0000000..385bd5e --- /dev/null +++ b/clang/test/OpenMP/target_dyn_groupprivate_messages.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=61 %s -Wuninitialized + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, class S> // expected-note {{declared here}} +int tmain(T argc, S **argv) { + T z; + #pragma omp target dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}} + foo(); + #pragma omp target dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate () // expected-error {{expected expression}} + foo(); + #pragma omp target dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + foo(); + #pragma omp target dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target' cannot contain more than one 'dyn_groupprivate' clause}} + foo(); + #pragma omp target dyn_groupprivate (S) // expected-error {{'S' does not refer to a value}} + foo(); + #pragma omp target dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(argc+z) + foo(); + return 0; +} + +int main(int argc, char **argv) { +constexpr int n = -1; +int z; + #pragma omp target dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}} + foo(); + #pragma omp target dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate () // expected-error {{expected expression}} + foo(); + #pragma omp target dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + foo(); + #pragma omp target dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target' cannot contain more than one 'dyn_groupprivate' clause}} + foo(); + #pragma omp target dyn_groupprivate (S1) // expected-error {{'S1' does not refer to a value}} + foo(); + #pragma omp target dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(dyn_groupprivate(tmain(argc, argv) // expected-error2 {{expected ')'}} expected-note2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}} + foo(); + #pragma omp target dyn_groupprivate(-1) // expected-error {{argument to 'dyn_groupprivate' clause must be a non-negative integer value}} + foo(); + #pragma omp target dyn_groupprivate(cgrou) // expected-error {{use of undeclared identifier 'cgrou'}} + foo(); + #pragma omp target dyn_groupprivate(cgrou: argc) // expected-error {{use of undeclared identifier 'cgrou'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(cgroup,cgroup: argc) // expected-error {{modifier 'cgroup' cannot be used along with modifier 'cgroup' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(default_mem),fallback(abort): argc) // expected-error {{modifier 'fallback(abort)' cannot be used along with modifier 'fallback(default_mem)' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(abort),fallback(null): argc) // expected-error {{modifier 'fallback(null)' cannot be used along with modifier 'fallback(abort)' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(cgroup): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(fallback(): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(: argc) // expected-error {{expected ')'}} expected-error {{expected expression}} expected-note {{to match this '('}} + foo(); + + return tmain(argc, argv); +} + diff --git a/clang/test/OpenMP/target_teams_dyn_groupprivate_messages.cpp b/clang/test/OpenMP/target_teams_dyn_groupprivate_messages.cpp new file mode 100644 index 0000000..ac2cc0d --- /dev/null +++ b/clang/test/OpenMP/target_teams_dyn_groupprivate_messages.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=61 %s -Wuninitialized + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, class S> // expected-note {{declared here}} +int tmain(T argc, S **argv) { + T z; + #pragma omp target teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}} + foo(); + #pragma omp target teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate () // expected-error {{expected expression}} + foo(); + #pragma omp target teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}} + foo(); + #pragma omp target teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + foo(); + #pragma omp target teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'dyn_groupprivate' clause}} + foo(); + #pragma omp target teams dyn_groupprivate (S) // expected-error {{'S' does not refer to a value}} + foo(); + #pragma omp target teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate(argc+z) + foo(); + return 0; +} + +int main(int argc, char **argv) { +constexpr int n = -1; +int z; + #pragma omp target teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}} + foo(); + #pragma omp target teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate () // expected-error {{expected expression}} + foo(); + #pragma omp target teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}} + foo(); + #pragma omp target teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + foo(); + #pragma omp target teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'dyn_groupprivate' clause}} + foo(); + #pragma omp target teams dyn_groupprivate (S1) // expected-error {{'S1' does not refer to a value}} + foo(); + #pragma omp target teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate(dyn_groupprivate(tmain(argc, argv) // expected-error2 {{expected ')'}} expected-note2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}} + foo(); + #pragma omp target teams dyn_groupprivate(-1) // expected-error {{argument to 'dyn_groupprivate' clause must be a non-negative integer value}} + foo(); + #pragma omp target teams dyn_groupprivate(cgrou) // expected-error {{use of undeclared identifier 'cgrou'}} + foo(); + #pragma omp target teams dyn_groupprivate(cgrou: argc) // expected-error {{use of undeclared identifier 'cgrou'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate(cgroup,cgroup: argc) // expected-error {{modifier 'cgroup' cannot be used along with modifier 'cgroup' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(default_mem),fallback(abort): argc) // expected-error {{modifier 'fallback(abort)' cannot be used along with modifier 'fallback(default_mem)' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(abort),fallback(null): argc) // expected-error {{modifier 'fallback(null)' cannot be used along with modifier 'fallback(abort)' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(cgroup): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(fallback(): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target teams dyn_groupprivate(: argc) // expected-error {{expected ')'}} expected-error {{expected expression}} expected-note {{to match this '('}} + foo(); + + return tmain(argc, argv); +} + diff --git a/clang/test/OpenMP/teams_dyn_groupprivate_messages.cpp b/clang/test/OpenMP/teams_dyn_groupprivate_messages.cpp new file mode 100644 index 0000000..701ebfb --- /dev/null +++ b/clang/test/OpenMP/teams_dyn_groupprivate_messages.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=61 %s -Wuninitialized + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template <class T, class S> // expected-note {{declared here}} +int tmain(T argc, S **argv) { + T z; + #pragma omp teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}} + foo(); + #pragma omp teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate () // expected-error {{expected expression}} + foo(); + #pragma omp teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams' are ignored}} + foo(); + #pragma omp teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + foo(); + #pragma omp teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp teams' cannot contain more than one 'dyn_groupprivate' clause}} + foo(); + #pragma omp teams dyn_groupprivate (S) // expected-error {{'S' does not refer to a value}} + foo(); + #pragma omp teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate(argc+z) + foo(); + return 0; +} + +int main(int argc, char **argv) { +constexpr int n = -1; +int z; + #pragma omp teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}} + foo(); + #pragma omp teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate () // expected-error {{expected expression}} + foo(); + #pragma omp teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams' are ignored}} + foo(); + #pragma omp teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + foo(); + #pragma omp teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp teams' cannot contain more than one 'dyn_groupprivate' clause}} + foo(); + #pragma omp teams dyn_groupprivate (S1) // expected-error {{'S1' does not refer to a value}} + foo(); + #pragma omp teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate(dyn_groupprivate(tmain(argc, argv) // expected-error2 {{expected ')'}} expected-note2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}} + foo(); + #pragma omp teams dyn_groupprivate(-1) // expected-error {{argument to 'dyn_groupprivate' clause must be a non-negative integer value}} + foo(); + #pragma omp teams dyn_groupprivate(cgrou) // expected-error {{use of undeclared identifier 'cgrou'}} + foo(); + #pragma omp teams dyn_groupprivate(cgrou: argc) // expected-error {{use of undeclared identifier 'cgrou'}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate(cgroup,cgroup: argc) // expected-error {{modifier 'cgroup' cannot be used along with modifier 'cgroup' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(default_mem),fallback(abort): argc) // expected-error {{modifier 'fallback(abort)' cannot be used along with modifier 'fallback(default_mem)' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(abort),fallback(null): argc) // expected-error {{modifier 'fallback(null)' cannot be used along with modifier 'fallback(abort)' in dyn_groupprivate}} + foo(); + #pragma omp target dyn_groupprivate(fallback(cgroup): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp target dyn_groupprivate(fallback(): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + #pragma omp teams dyn_groupprivate(: argc) // expected-error {{expected ')'}} expected-error {{expected expression}} expected-note {{to match this '('}} + foo(); + + return tmain(argc, argv); +} + diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index c11a348..5f5bf42 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -87,7 +87,7 @@ static std::string ModuleFilesDir; static bool EagerLoadModules; static unsigned NumThreads = 0; static std::string CompilationDB; -static std::optional<std::string> ModuleName; +static std::optional<std::string> ModuleNames; static std::vector<std::string> ModuleDepTargets; static std::string TranslationUnitFile; static bool DeprecatedDriverCommand; @@ -205,8 +205,8 @@ static void ParseArgs(int argc, char **argv) { if (const llvm::opt::Arg *A = Args.getLastArg(OPT_compilation_database_EQ)) CompilationDB = A->getValue(); - if (const llvm::opt::Arg *A = Args.getLastArg(OPT_module_name_EQ)) - ModuleName = A->getValue(); + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_module_names_EQ)) + ModuleNames = A->getValue(); for (const llvm::opt::Arg *A : Args.filtered(OPT_dependency_target_EQ)) ModuleDepTargets.emplace_back(A->getValue()); @@ -664,6 +664,16 @@ static bool handleModuleResult(StringRef ModuleName, return false; } +static void handleErrorWithInfoString(StringRef Info, llvm::Error E, + SharedStream &OS, SharedStream &Errs) { + llvm::handleAllErrors(std::move(E), [&Info, &Errs](llvm::StringError &Err) { + Errs.applyLocked([&](raw_ostream &OS) { + OS << "Error: " << Info << ":\n"; + OS << Err.getMessage(); + }); + }); +} + class P1689Deps { public: void printDependencies(raw_ostream &OS) { @@ -1008,7 +1018,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { }; if (Format == ScanningOutputFormat::Full) - FD.emplace(!ModuleName ? Inputs.size() : 0); + FD.emplace(!ModuleNames ? Inputs.size() : 0); std::atomic<size_t> NumStatusCalls = 0; std::atomic<size_t> NumOpenFileForReadCalls = 0; @@ -1082,13 +1092,48 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { MakeformatOS, Errs)) HadErrors = true; } - } else if (ModuleName) { - auto MaybeModuleDepsGraph = WorkerTool.getModuleDependencies( - *ModuleName, Input->CommandLine, CWD, AlreadySeenModules, - LookupOutput); - if (handleModuleResult(*ModuleName, MaybeModuleDepsGraph, *FD, - LocalIndex, DependencyOS, Errs)) - HadErrors = true; + } else if (ModuleNames) { + StringRef ModuleNameRef(*ModuleNames); + SmallVector<StringRef> Names; + ModuleNameRef.split(Names, ','); + + if (Names.size() == 1) { + auto MaybeModuleDepsGraph = WorkerTool.getModuleDependencies( + Names[0], Input->CommandLine, CWD, AlreadySeenModules, + LookupOutput); + if (handleModuleResult(Names[0], MaybeModuleDepsGraph, *FD, + LocalIndex, DependencyOS, Errs)) + HadErrors = true; + } else { + if (llvm::Error Err = + WorkerTool.initializeCompilerInstanceWithContext( + CWD, Input->CommandLine)) { + handleErrorWithInfoString( + "Compiler instance with context setup error", std::move(Err), + DependencyOS, Errs); + HadErrors = true; + continue; + } + + for (auto N : Names) { + auto MaybeModuleDepsGraph = + WorkerTool.computeDependenciesByNameWithContext( + N, AlreadySeenModules, LookupOutput); + if (handleModuleResult(N, MaybeModuleDepsGraph, *FD, LocalIndex, + DependencyOS, Errs)) { + HadErrors = true; + break; + } + } + + if (llvm::Error Err = + WorkerTool.finalizeCompilerInstanceWithContext()) { + handleErrorWithInfoString( + "Compiler instance with context finialization error", + std::move(Err), DependencyOS, Errs); + HadErrors = true; + } + } } else { std::unique_ptr<llvm::MemoryBuffer> TU; std::optional<llvm::MemoryBufferRef> TUBuffer; diff --git a/clang/tools/clang-scan-deps/Opts.td b/clang/tools/clang-scan-deps/Opts.td index 7a63b18..6ea9d82 100644 --- a/clang/tools/clang-scan-deps/Opts.td +++ b/clang/tools/clang-scan-deps/Opts.td @@ -26,7 +26,9 @@ def eager_load_pcm : F<"eager-load-pcm", "Load PCM files eagerly (instead of laz def j : Arg<"j", "Number of worker threads to use (default: use all concurrent threads)">; defm compilation_database : Eq<"compilation-database", "Compilation database">; -defm module_name : Eq<"module-name", "the module of which the dependencies are to be computed">; +defm module_names + : Eq<"module-names", "A comma separated list of names of modules of which " + "the dependencies are to be computed">; defm dependency_target : Eq<"dependency-target", "The names of dependency targets for the dependency file">; defm tu_buffer_path: Eq<"tu-buffer-path", "The path to the translation unit for depscan. Not compatible with -module-name">; diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 08776d9..f4d6fa7 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2757,6 +2757,11 @@ void OMPClauseEnqueue::VisitOMPXDynCGroupMemClause( VisitOMPClauseWithPreInit(C); Visitor->AddStmt(C->getSize()); } +void OMPClauseEnqueue::VisitOMPDynGroupprivateClause( + const OMPDynGroupprivateClause *C) { + VisitOMPClauseWithPreInit(C); + Visitor->AddStmt(C->getSize()); +} void OMPClauseEnqueue::VisitOMPDoacrossClause(const OMPDoacrossClause *C) { VisitOMPClauseList(C); } diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 43b2117..d578fa7 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -589,20 +589,20 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("AlignTrailingComments: Leave", AlignTrailingComments, FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Leave, 0})); + {FormatStyle::TCAS_Leave, 0, true})); CHECK_PARSE("AlignTrailingComments: Always", AlignTrailingComments, FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Always, 0})); + {FormatStyle::TCAS_Always, 0, true})); CHECK_PARSE("AlignTrailingComments: Never", AlignTrailingComments, FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Never, 0})); + {FormatStyle::TCAS_Never, 0, true})); // For backwards compatibility CHECK_PARSE("AlignTrailingComments: true", AlignTrailingComments, FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Always, 0})); + {FormatStyle::TCAS_Always, 0, true})); CHECK_PARSE("AlignTrailingComments: false", AlignTrailingComments, FormatStyle::TrailingCommentsAlignmentStyle( - {FormatStyle::TCAS_Never, 0})); + {FormatStyle::TCAS_Never, 0, true})); CHECK_PARSE_NESTED_VALUE("Kind: Always", AlignTrailingComments, Kind, FormatStyle::TCAS_Always); CHECK_PARSE_NESTED_VALUE("Kind: Never", AlignTrailingComments, Kind, @@ -611,6 +611,7 @@ TEST(ConfigParseTest, ParsesConfiguration) { FormatStyle::TCAS_Leave); CHECK_PARSE_NESTED_VALUE("OverEmptyLines: 1234", AlignTrailingComments, OverEmptyLines, 1234u); + CHECK_PARSE_NESTED_BOOL(AlignTrailingComments, AlignPPAndNotPP); Style.UseTab = FormatStyle::UT_ForIndentation; CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never); diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index d7b2257..684d301 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -3378,6 +3378,66 @@ TEST_F(FormatTestComments, DontAlignOverScope) { "int foobar; // group"); } +TEST_F(FormatTestComments, DontAlignOverPPDirective) { + auto Style = getLLVMStyle(); + Style.AlignTrailingComments.AlignPPAndNotPP = false; + + verifyFormat("int i; // Aligned\n" + "int long; // with this\n" + "#define FOO // only aligned\n" + "#define LOOONG // with other pp directives\n" + "int loooong; // new alignment", + "int i;//Aligned\n" + "int long;//with this\n" + "#define FOO //only aligned\n" + "#define LOOONG //with other pp directives\n" + "int loooong; //new alignment", + Style); + + verifyFormat("#define A // Comment\n" + "#define AB // Comment", + Style); + + Style.ColumnLimit = 30; + verifyNoChange("#define A // Comment\n" + " // Continued\n" + "int i = 0; // New Stuff\n" + " // Continued\n" + "#define Func(X) \\\n" + " X(); \\\n" + " X(); // Comment\n" + " // Continued\n" + "long loong = 1; // Dont align", + Style); + + verifyFormat("#define A // Comment that\n" + " // would wrap\n" + "#define FOO // For the\n" + " // alignment\n" + "#define B // Also\n" + " // aligned", + "#define A // Comment that would wrap\n" + "#define FOO // For the alignment\n" + "#define B // Also\n" + " // aligned", + Style); + + Style.AlignTrailingComments.OverEmptyLines = 1; + verifyNoChange("#define A // Comment\n" + "\n" + " // Continued\n" + "int i = 0; // New Stuff\n" + "\n" + " // Continued\n" + "#define Func(X) \\\n" + " X(); \\\n" + " X(); // Comment\n" + "\n" + " // Continued\n" + "long loong = 1; // Dont align", + Style); +} + TEST_F(FormatTestComments, AlignsBlockCommentDecorations) { verifyFormat("/*\n" " */", |
