diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-01 13:24:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-01 13:24:05 +0000 |
commit | cf1b401909b5e54edfd80656b1a18eaa31f9f6f1 (patch) | |
tree | edb0ffff2a43d84ba9b4c862b394cfeeebb36ddc | |
parent | ef915aab0ac566c55bfb0d7a9f6635bb5d94d4af (diff) |
Vendor import of clang trunk r306956:vendor/clang/clang-trunk-r306956
Notes
Notes:
svn path=/vendor/clang/dist/; revision=320535
svn path=/vendor/clang/clang-trunk-r306956/; revision=320536; tag=vendor/clang/clang-trunk-r306956
278 files changed, 9540 insertions, 2797 deletions
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 8440b0aabe08..5e70bde770f8 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -1367,6 +1367,30 @@ TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2) TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3) TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4) +### Exception Specification Kinds ### +class ExceptionSpecificationKind(BaseEnumeration): + """ + An ExceptionSpecificationKind describes the kind of exception specification + that a function has. + """ + + # The required BaseEnumeration declarations. + _kinds = [] + _name_map = None + + def __repr__(self): + return 'ExceptionSpecificationKind.{}'.format(self.name) + +ExceptionSpecificationKind.NONE = ExceptionSpecificationKind(0) +ExceptionSpecificationKind.DYNAMIC_NONE = ExceptionSpecificationKind(1) +ExceptionSpecificationKind.DYNAMIC = ExceptionSpecificationKind(2) +ExceptionSpecificationKind.MS_ANY = ExceptionSpecificationKind(3) +ExceptionSpecificationKind.BASIC_NOEXCEPT = ExceptionSpecificationKind(4) +ExceptionSpecificationKind.COMPUTED_NOEXCEPT = ExceptionSpecificationKind(5) +ExceptionSpecificationKind.UNEVALUATED = ExceptionSpecificationKind(6) +ExceptionSpecificationKind.UNINSTANTIATED = ExceptionSpecificationKind(7) +ExceptionSpecificationKind.UNPARSED = ExceptionSpecificationKind(8) + ### Cursors ### class Cursor(Structure): @@ -1587,6 +1611,18 @@ class Cursor(Structure): return self._result_type @property + def exception_specification_kind(self): + ''' + Retrieve the exception specification kind, which is one of the values + from the ExceptionSpecificationKind enumeration. + ''' + if not hasattr(self, '_exception_specification_kind'): + exc_kind = conf.lib.clang_getCursorExceptionSpecificationType(self) + self._exception_specification_kind = ExceptionSpecificationKind.from_id(exc_kind) + + return self._exception_specification_kind + + @property def underlying_typedef_type(self): """Return the underlying type of a typedef declaration. @@ -2254,6 +2290,14 @@ class Type(Structure): callbacks['fields_visit'](visitor), fields) return iter(fields) + def get_exception_specification_kind(self): + """ + Return the kind of the exception specification; a value from + the ExceptionSpecificationKind enumeration. + """ + return ExceptionSpecificationKind.from_id( + conf.lib.clang.getExceptionSpecificationType(self)) + @property def spelling(self): """Retrieve the spelling of this Type.""" diff --git a/bindings/python/tests/test_exception_specification_kind.py b/bindings/python/tests/test_exception_specification_kind.py new file mode 100644 index 000000000000..543d47f7db97 --- /dev/null +++ b/bindings/python/tests/test_exception_specification_kind.py @@ -0,0 +1,27 @@ +import clang.cindex +from clang.cindex import ExceptionSpecificationKind +from .util import get_tu + + +def find_function_declarations(node, declarations=[]): + if node.kind == clang.cindex.CursorKind.FUNCTION_DECL: + declarations.append((node.spelling, node.exception_specification_kind)) + for child in node.get_children(): + declarations = find_function_declarations(child, declarations) + return declarations + + +def test_exception_specification_kind(): + source = """int square1(int x); + int square2(int x) noexcept; + int square3(int x) noexcept(noexcept(x * x));""" + + tu = get_tu(source, lang='cpp', flags=['-std=c++14']) + + declarations = find_function_declarations(tu.cursor) + expected = [ + ('square1', ExceptionSpecificationKind.NONE), + ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT), + ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT) + ] + assert declarations == expected diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index 7362456202ba..df6344af9102 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -322,18 +322,27 @@ output format of the diagnostics that it generates. by category, so it should be a high level category. We want dozens of these, not hundreds or thousands of them. +.. _opt_fsave-optimization-record: + +**-fsave-optimization-record** + Write optimization remarks to a YAML file. + + This option, which defaults to off, controls whether Clang writes + optimization reports to a YAML file. By recording diagnostics in a file, + using a structured YAML format, users can parse or sort the remarks in a + convenient way. + .. _opt_fdiagnostics-show-hotness: **-f[no-]diagnostics-show-hotness** Enable profile hotness information in diagnostic line. - This option, which defaults to off, controls whether Clang prints the - profile hotness associated with a diagnostics in the presence of - profile-guided optimization information. This is currently supported with - optimization remarks (see :ref:`Options to Emit Optimization Reports - <rpass>`). The hotness information allows users to focus on the hot - optimization remarks that are likely to be more relevant for run-time - performance. + This option controls whether Clang prints the profile hotness associated + with diagnostics in the presence of profile-guided optimization information. + This is currently supported with optimization remarks (see + :ref:`Options to Emit Optimization Reports <rpass>`). The hotness information + allows users to focus on the hot optimization remarks that are likely to be + more relevant for run-time performance. For example, in this output, the block containing the callsite of `foo` was executed 3000 times according to the profile data: @@ -344,6 +353,23 @@ output format of the diagnostics that it generates. sum += foo(x, x - 2); ^ + This option is implied when + :ref:`-fsave-optimization-record <opt_fsave-optimization-record>` is used. + Otherwise, it defaults to off. + +.. _opt_fdiagnostics-hotness-threshold: + +**-fdiagnostics-hotness-threshold** + Prevent optimization remarks from being output if they do not have at least + this hotness value. + + This option, which defaults to zero, controls the minimum hotness an + optimization remark would need in order to be output by Clang. This is + currently supported with optimization remarks (see :ref:`Options to Emit + Optimization Reports <rpass>`) when profile hotness information in + diagnostics is enabled (see + :ref:`-fdiagnostics-show-hotness <opt_fdiagnostics-show-hotness>`). + .. _opt_fdiagnostics-fixit-info: **-f[no-]diagnostics-fixit-info** diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 4241e43a9697..f404e6d72ec9 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -171,7 +171,60 @@ typedef struct CXVersion { */ int Subminor; } CXVersion; - + +/** + * \brief Describes the exception specification of a cursor. + * + * A negative value indicates that the cursor is not a function declaration. + */ +enum CXCursor_ExceptionSpecificationKind { + + /** + * \brief The cursor has no exception specification. + */ + CXCursor_ExceptionSpecificationKind_None, + + /** + * \brief The cursor has exception specification throw() + */ + CXCursor_ExceptionSpecificationKind_DynamicNone, + + /** + * \brief The cursor has exception specification throw(T1, T2) + */ + CXCursor_ExceptionSpecificationKind_Dynamic, + + /** + * \brief The cursor has exception specification throw(...). + */ + CXCursor_ExceptionSpecificationKind_MSAny, + + /** + * \brief The cursor has exception specification basic noexcept. + */ + CXCursor_ExceptionSpecificationKind_BasicNoexcept, + + /** + * \brief The cursor has exception specification computed noexcept. + */ + CXCursor_ExceptionSpecificationKind_ComputedNoexcept, + + /** + * \brief The exception specification has not yet been evaluated. + */ + CXCursor_ExceptionSpecificationKind_Unevaluated, + + /** + * \brief The exception specification has not yet been instantiated. + */ + CXCursor_ExceptionSpecificationKind_Uninstantiated, + + /** + * \brief The exception specification has not been parsed yet. + */ + CXCursor_ExceptionSpecificationKind_Unparsed +}; + /** * \brief Provides a shared context for creating translation units. * @@ -3471,6 +3524,13 @@ CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T); CINDEX_LINKAGE CXType clang_getResultType(CXType T); /** + * \brief Retrieve the exception specification type associated with a function type. + * + * If a non-function type is passed in, an error code of -1 is returned. + */ +CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T); + +/** * \brief Retrieve the number of non-variadic parameters associated with a * function type. * @@ -3499,6 +3559,13 @@ CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T); CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); /** + * \brief Retrieve the exception specification type associated with a given cursor. + * + * This only returns a valid result if the cursor refers to a function or method. + */ +CINDEX_LINKAGE int clang_getCursorExceptionSpecificationType(CXCursor C); + +/** * \brief Return 1 if the CXType is a POD (plain old data) type, and 0 * otherwise. */ diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 4c379620ab2d..3b46d31458ce 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -2050,6 +2050,11 @@ public: /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits. uint64_t getFieldOffset(const ValueDecl *FD) const; + /// Get the offset of an ObjCIvarDecl in bits. + uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, + const ObjCImplementationDecl *ID, + const ObjCIvarDecl *Ivar) const; + bool isNearlyEmpty(const CXXRecordDecl *RD) const; VTableContextBase *getVTableContext(); diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h index 770bb5763fbd..23674c65f332 100644 --- a/include/clang/AST/ASTStructuralEquivalence.h +++ b/include/clang/AST/ASTStructuralEquivalence.h @@ -62,9 +62,11 @@ struct StructuralEquivalenceContext { StructuralEquivalenceContext( ASTContext &FromCtx, ASTContext &ToCtx, llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls, - bool StrictTypeSpelling = false, bool Complain = true) + bool StrictTypeSpelling = false, bool Complain = true, + bool ErrorOnTagTypeMismatch = false) : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling), Complain(Complain), + StrictTypeSpelling(StrictTypeSpelling), + ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain), LastDiagFromC2(false) {} DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 30552be9b381..08b34a75aa60 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2019,7 +2019,10 @@ public: /// These functions have special behavior under C++1y [expr.new]: /// An implementation is allowed to omit a call to a replaceable global /// allocation function. [...] - bool isReplaceableGlobalAllocationFunction() const; + /// + /// If this function is an aligned allocation/deallocation function, return + /// true through IsAligned. + bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const; /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 583f9d9f1deb..3757116e7c70 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -49,7 +49,7 @@ public: NSStr_initWithString, NSStr_initWithUTF8String }; - static const unsigned NumNSStringMethods = 5; + static const unsigned NumNSStringMethods = 6; IdentifierInfo *getNSClassId(NSClassIdKindKind K) const; @@ -112,7 +112,7 @@ public: NSMutableDict_setObjectForKeyedSubscript, NSMutableDict_setValueForKey }; - static const unsigned NumNSDictionaryMethods = 14; + static const unsigned NumNSDictionaryMethods = 13; /// \brief The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index f977e63e04f6..14e73819f53d 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -20,6 +20,7 @@ #include "clang/AST/Stmt.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/MapVector.h" namespace clang { @@ -3001,7 +3002,7 @@ protected: // Organize the components by declaration and retrieve the original // expression. Original expressions are always the first component of the // mappable component list. - llvm::DenseMap<ValueDecl *, SmallVector<MappableExprComponentListRef, 8>> + llvm::MapVector<ValueDecl *, SmallVector<MappableExprComponentListRef, 8>> ComponentListMap; { auto CI = ComponentLists.begin(); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index ad3f40d0d3f6..152e05bca740 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -593,6 +593,16 @@ bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) { #define STMT(CLASS, PARENT) \ case Stmt::CLASS##Class: \ TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break; +#define INITLISTEXPR(CLASS, PARENT) \ + case Stmt::CLASS##Class: \ + { \ + auto ILE = static_cast<CLASS *>(S); \ + if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \ + TRY_TO(WalkUpFrom##CLASS(Syn)); \ + if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \ + TRY_TO(WalkUpFrom##CLASS(Sem)); \ + break; \ + } #include "clang/AST/StmtNodes.inc" } @@ -2220,13 +2230,15 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( // the syntactic and the semantic form. // // There is no guarantee about which form \p S takes when this method is called. -DEF_TRAVERSE_STMT(InitListExpr, { +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseInitListExpr( + InitListExpr *S, DataRecursionQueue *Queue) { TRY_TO(TraverseSynOrSemInitListExpr( S->isSemanticForm() ? S->getSyntacticForm() : S, Queue)); TRY_TO(TraverseSynOrSemInitListExpr( S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); - ShouldVisitChildren = false; -}) + return true; +} // GenericSelectionExpr is a special case because the types and expressions // are interleaved. We also need to watch out for null types (default diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index cd5f186a2086..89a9d3c4cc21 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -21,6 +21,60 @@ namespace clang { class ASTContext; +// Some notes on redeclarables: +// +// - Every redeclarable is on a circular linked list. +// +// - Every decl has a pointer to the first element of the chain _and_ a +// DeclLink that may point to one of 3 possible states: +// - the "previous" (temporal) element in the chain +// - the "latest" (temporal) element in the chain +// - the an "uninitialized-latest" value (when newly-constructed) +// +// - The first element is also often called the canonical element. Every +// element has a pointer to it so that "getCanonical" can be fast. +// +// - Most links in the chain point to previous, except the link out of +// the first; it points to latest. +// +// - Elements are called "first", "previous", "latest" or +// "most-recent" when referring to temporal order: order of addition +// to the chain. +// +// - To make matters confusing, the DeclLink type uses the term "next" +// for its pointer-storage internally (thus functions like +// NextIsPrevious). It's easiest to just ignore the implementation of +// DeclLink when making sense of the redeclaration chain. +// +// - There's also a "definition" link for several types of +// redeclarable, where only one definition should exist at any given +// time (and the defn pointer is stored in the decl's "data" which +// is copied to every element on the chain when it's changed). +// +// Here is some ASCII art: +// +// "first" "latest" +// "canonical" "most recent" +// +------------+ first +--------------+ +// | | <--------------------------- | | +// | | | | +// | | | | +// | | +--------------+ | | +// | | first | | | | +// | | <---- | | | | +// | | | | | | +// | @class A | link | @interface A | link | @class A | +// | seen first | <---- | seen second | <---- | seen third | +// | | | | | | +// +------------+ +--------------+ +--------------+ +// | data | defn | data | defn | data | +// | | ----> | | <---- | | +// +------------+ +--------------+ +--------------+ +// | | ^ ^ +// | |defn | | +// | link +-----+ | +// +-->-------------------------------------------+ + /// \brief Provides common interface for the Decls that can be redeclared. template<typename decl_type> class Redeclarable { diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 65dd7445ba26..2987f07d8bb4 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -605,20 +605,27 @@ semantics: for ``T`` and ``U`` to be incompatible. The declaration of ``overloadable`` functions is restricted to function -declarations and definitions. Most importantly, if any function with a given -name is given the ``overloadable`` attribute, then all function declarations -and definitions with that name (and in that scope) must have the -``overloadable`` attribute. This rule even applies to redeclarations of -functions whose original declaration had the ``overloadable`` attribute, e.g., +declarations and definitions. If a function is marked with the ``overloadable`` +attribute, then all declarations and definitions of functions with that name, +except for at most one (see the note below about unmarked overloads), must have +the ``overloadable`` attribute. In addition, redeclarations of a function with +the ``overloadable`` attribute must have the ``overloadable`` attribute, and +redeclarations of a function without the ``overloadable`` attribute must *not* +have the ``overloadable`` attribute. e.g., .. code-block:: c int f(int) __attribute__((overloadable)); float f(float); // error: declaration of "f" must have the "overloadable" attribute + int f(int); // error: redeclaration of "f" must have the "overloadable" attribute int g(int) __attribute__((overloadable)); int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute + int h(int); + int h(int) __attribute__((overloadable)); // error: declaration of "h" must not + // have the "overloadable" attribute + Functions marked ``overloadable`` must have prototypes. Therefore, the following code is ill-formed: @@ -651,7 +658,28 @@ caveats to this use of name mangling: linkage specification, it's name *will* be mangled in the same way as it would in C. -Query for this feature with ``__has_extension(attribute_overloadable)``. +For the purpose of backwards compatibility, at most one function with the same +name as other ``overloadable`` functions may omit the ``overloadable`` +attribute. In this case, the function without the ``overloadable`` attribute +will not have its name mangled. + +For example: + +.. code-block:: c + + // Notes with mangled names assume Itanium mangling. + int f(int); + int f(double) __attribute__((overloadable)); + void foo() { + f(5); // Emits a call to f (not _Z1fi, as it would with an overload that + // was marked with overloadable). + f(1.0); // Emits a call to _Z1fd. + } + +Support for unmarked overloads is not present in some versions of clang. You may +query for it using ``__has_extension(overloadable_unmarked)``. + +Query for this attribute with ``__has_attribute(overloadable)``. }]; } diff --git a/include/clang/Basic/BuiltinsNios2.def b/include/clang/Basic/BuiltinsNios2.def new file mode 100644 index 000000000000..d9697e795c44 --- /dev/null +++ b/include/clang/Basic/BuiltinsNios2.def @@ -0,0 +1,70 @@ +//===-- BuiltinsNios2.def - Nios2 Builtin function database --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Nios2-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +#if defined(BUILTIN) && !defined(TARGET_BUILTIN) +# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) +#endif + +// Nios2 R1 builtins: + +//int __builtin_ldbio(volatile const void *); +BUILTIN(__builtin_ldbio, "ivDC*", "") +//int __builtin_ldbuio(volatile const void *); +BUILTIN(__builtin_ldbuio, "ivDC*", "") +//int __builtin_ldhio(volatile const void *); +BUILTIN(__builtin_ldhio, "ivDC*", "") +//int __builtin_ldhuio(volatile const void *); +BUILTIN(__builtin_ldhuio, "ivDC*", "") +//int __builtin_ldwio(volatile const void *); +BUILTIN(__builtin_ldwio, "ivDC*", "") +//int __builtin_ldwuio(int); +BUILTIN(__builtin_ldwuio, "ii", "") +// int __builtin_rdctl(int); +BUILTIN(__builtin_rdctl, "iIi", "") +// void __builtin_wrctl(int, int); +BUILTIN(__builtin_wrctl, "vIii", "") +// int __builtin_rdprs(int, int); +BUILTIN(__builtin_rdprs, "iii", "") +//void __builtin_stbio(volatile void *, int); +BUILTIN(__builtin_stbio, "vvD*i", "") +//void __builtin_sthio(volatile void *, int); +BUILTIN(__builtin_sthio, "vvD*i", "") +//void __builtin_stwio(volatile void *, int); +BUILTIN(__builtin_stwio, "vvD*i", "") +//void __builtin_sync(void); +BUILTIN(__builtin_sync, "v", "") +// void __builtin_flushd(volatile void *); +BUILTIN(__builtin_flushd, "vvD*", "") +// void __builtin_flushda(volatile void *); +BUILTIN(__builtin_flushda, "vvD*", "") + +// Nios2 R2 builtins: + +// int __builtin_wrpie(int); +TARGET_BUILTIN(__builtin_wrpie, "ii", "", "nios2r2mandatory") +// void __builtin_eni(int); +TARGET_BUILTIN(__builtin_eni, "vi", "", "nios2r2mandatory") +// int __builtin_ldex(volatile const void *); +TARGET_BUILTIN(__builtin_ldex, "ivDC*", "", "nios2r2mandatory") +// int __builtin_stex(volatile void *, int); +TARGET_BUILTIN(__builtin_stex, "ivD*i", "", "nios2r2mandatory") +// int __builtin_ldsex(volatile const void *); +TARGET_BUILTIN(__builtin_ldsex, "ivDC*", "", "nios2r2mpx") +// int __builtin_stsex(volatile void *, int); +TARGET_BUILTIN(__builtin_stsex, "ivDC*i", "", "nios2r2mpx") + +#undef BUILTIN +#undef TARGET_BUILTIN diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def index de56908be83c..19318dcebb9e 100644 --- a/include/clang/Basic/BuiltinsWebAssembly.def +++ b/include/clang/Basic/BuiltinsWebAssembly.def @@ -21,4 +21,8 @@ BUILTIN(__builtin_wasm_current_memory, "z", "n") BUILTIN(__builtin_wasm_grow_memory, "zz", "n") +// Exception handling builtins. +BUILTIN(__builtin_wasm_throw, "vUiv*", "r") +BUILTIN(__builtin_wasm_rethrow, "v", "r") + #undef BUILTIN diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index 652d06278557..b3cba2066edd 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -200,12 +200,17 @@ def note_odr_defined_here : Note<"also defined here">; def err_odr_function_type_inconsistent : Error< "external function %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; -def warn_odr_tag_type_inconsistent : Warning< - "type %0 has incompatible definitions in different translation units">, - InGroup<DiagGroup<"odr">>; +def warn_odr_tag_type_inconsistent + : Warning<"type %0 has incompatible definitions in different translation " + "units">, + InGroup<DiagGroup<"odr">>; +def err_odr_tag_type_inconsistent + : Error<"type %0 has incompatible definitions in different translation " + "units">; def note_odr_tag_kind_here: Note< "%0 is a %select{struct|interface|union|class|enum}1 here">; def note_odr_field : Note<"field %0 has type %1 here">; +def note_odr_field_name : Note<"field has name %0 here">; def note_odr_missing_field : Note<"no corresponding field here">; def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">; def note_odr_not_bit_field : Note<"field %0 is not a bit-field">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index eb6dd37c148d..42e1e5edaf9e 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -138,6 +138,9 @@ def err_drv_cc_print_options_failure : Error< def err_drv_lto_without_lld : Error<"LTO requires -fuse-ld=lld">; def err_drv_preamble_format : Error< "incorrect format for -preamble-bytes=N,END">; +def err_invalid_ios_deployment_target : Error< + "invalid iOS deployment version '%0', iOS 10 is the maximum deployment " + "target for 32-bit targets">; def err_drv_conflicting_deployment_targets : Error< "conflicting deployment targets, both '%0' and '%1' are present in environment">; def err_arc_unsupported_on_runtime : Error< @@ -195,8 +198,8 @@ def warn_drv_unused_argument : Warning< def warn_drv_empty_joined_argument : Warning< "joined argument expects additional value: '%0'">, InGroup<UnusedCommandLineArgument>; -def warn_drv_fdiagnostics_show_hotness_requires_pgo : Warning< - "argument '-fdiagnostics-show-hotness' requires profile-guided optimization information">, +def warn_drv_diagnostics_hotness_requires_pgo : Warning< + "argument '%0' requires profile-guided optimization information">, InGroup<UnusedCommandLineArgument>; def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 464c2425a1f1..3a0564806b32 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -311,6 +311,7 @@ def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; def : DiagGroup<"effc++", [NonVirtualDtor]>; def OveralignedType : DiagGroup<"over-aligned">; +def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">; def OldStyleCast : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index cba9b251215a..136e48ab5e54 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3294,13 +3294,15 @@ def warn_iboutletcollection_property_assign : Warning< "IBOutletCollection properties should be copy/strong and not assign">, InGroup<ObjCInvalidIBOutletProperty>; -def err_attribute_overloadable_missing : Error< - "%select{overloaded function|redeclaration of}0 %1 must have the " - "'overloadable' attribute">; +def err_attribute_overloadable_mismatch : Error< + "redeclaration of %0 must %select{not |}1have the 'overloadable' attribute">; def note_attribute_overloadable_prev_overload : Note< - "previous overload of function is here">; + "previous %select{unmarked |}0overload of function is here">; def err_attribute_overloadable_no_prototype : Error< "'overloadable' function %0 must have a prototype">; +def err_attribute_overloadable_multiple_unmarked_overloads : Error< + "at most one overload for a given name may lack the 'overloadable' " + "attribute">; def warn_ns_attribute_wrong_return_type : Warning< "%0 attribute only applies to %select{functions|methods|properties}1 that " "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">, @@ -6405,6 +6407,12 @@ def warn_overaligned_type : Warning< "type %0 requires %1 bytes of alignment and the default allocator only " "guarantees %2 bytes">, InGroup<OveralignedType>, DefaultIgnore; +def warn_aligned_allocation_unavailable :Warning< + "aligned %select{allocation|deallocation}0 function of type '%1' possibly " + "unavailable on %2">, InGroup<AlignedAllocationUnavailable>, DefaultError; +def note_silence_unligned_allocation_unavailable : Note< + "if you supply your own aligned allocation functions, use " + "-Wno-aligned-allocation-unavailable to silence this diagnostic">; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " @@ -8402,7 +8410,7 @@ def warn_opencl_attr_deprecated_ignored : Warning < def err_opencl_variadic_function : Error< "invalid prototype, variadic arguments are not allowed in OpenCL">; def err_opencl_requires_extension : Error< - "use of %select{type |declaration}0%1 requires %2 extension to be enabled">; + "use of %select{type|declaration}0 %1 requires %2 extension to be enabled">; // OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions def err_opencl_builtin_pipe_first_arg : Error< diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 60c8a68cd2e9..dfdad108922a 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -199,6 +199,7 @@ LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") +LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable") LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'") LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts") BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation") diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index 74ec26f19ac2..aae1c3a9b8c5 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -552,6 +552,7 @@ OPENMP_TASKLOOP_CLAUSE(priority) OPENMP_TASKLOOP_CLAUSE(grainsize) OPENMP_TASKLOOP_CLAUSE(nogroup) OPENMP_TASKLOOP_CLAUSE(num_tasks) +OPENMP_TASKLOOP_CLAUSE(reduction) // Clauses allowed for OpenMP directive 'taskloop simd'. OPENMP_TASKLOOP_SIMD_CLAUSE(if) @@ -572,6 +573,7 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(simdlen) OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize) OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup) OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks) +OPENMP_TASKLOOP_SIMD_CLAUSE(reduction) // Clauses allowed for OpenMP directive 'critical'. OPENMP_CRITICAL_CLAUSE(hint) diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index f0fe4c27062e..12aa0e4f5717 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -262,6 +262,65 @@ public: bool isInvalid() const { return !isValid(); } }; +/// \brief Represents an unpacked "presumed" location which can be presented +/// to the user. +/// +/// A 'presumed' location can be modified by \#line and GNU line marker +/// directives and is always the expansion point of a normal location. +/// +/// You can get a PresumedLoc from a SourceLocation with SourceManager. +class PresumedLoc { + const char *Filename; + unsigned Line, Col; + SourceLocation IncludeLoc; + +public: + PresumedLoc() : Filename(nullptr) {} + PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) + : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {} + + /// \brief Return true if this object is invalid or uninitialized. + /// + /// This occurs when created with invalid source locations or when walking + /// off the top of a \#include stack. + bool isInvalid() const { return Filename == nullptr; } + bool isValid() const { return Filename != nullptr; } + + /// \brief Return the presumed filename of this location. + /// + /// This can be affected by \#line etc. + const char *getFilename() const { + assert(isValid()); + return Filename; + } + + /// \brief Return the presumed line number of this location. + /// + /// This can be affected by \#line etc. + unsigned getLine() const { + assert(isValid()); + return Line; + } + + /// \brief Return the presumed column number of this location. + /// + /// This cannot be affected by \#line, but is packaged here for convenience. + unsigned getColumn() const { + assert(isValid()); + return Col; + } + + /// \brief Return the presumed include location of this location. + /// + /// This can be affected by GNU linemarker directives. + SourceLocation getIncludeLoc() const { + assert(isValid()); + return IncludeLoc; + } +}; + +class FileEntry; + /// \brief A SourceLocation and its associated SourceManager. /// /// This is useful for argument passing to functions that expect both objects. @@ -274,6 +333,12 @@ public: explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} + bool hasManager() const { + bool hasSrcMgr = SrcMgr != nullptr; + assert(hasSrcMgr == isValid() && "FullSourceLoc has location but no manager"); + return hasSrcMgr; + } + /// \pre This FullSourceLoc has an associated SourceManager. const SourceManager &getManager() const { assert(SrcMgr && "SourceManager is NULL."); @@ -284,6 +349,13 @@ public: FullSourceLoc getExpansionLoc() const; FullSourceLoc getSpellingLoc() const; + FullSourceLoc getFileLoc() const; + std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const; + PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const; + bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const; + FullSourceLoc getImmediateMacroCallerLoc() const; + std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const; + unsigned getFileOffset() const; unsigned getExpansionLineNumber(bool *Invalid = nullptr) const; unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const; @@ -293,6 +365,12 @@ public: const char *getCharacterData(bool *Invalid = nullptr) const; + unsigned getLineNumber(bool *Invalid = nullptr) const; + unsigned getColumnNumber(bool *Invalid = nullptr) const; + + std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const; + + const FileEntry *getFileEntry() const; /// \brief Return a StringRef to the source buffer data for the /// specified FileID. @@ -345,50 +423,6 @@ public: }; -/// \brief Represents an unpacked "presumed" location which can be presented -/// to the user. -/// -/// A 'presumed' location can be modified by \#line and GNU line marker -/// directives and is always the expansion point of a normal location. -/// -/// You can get a PresumedLoc from a SourceLocation with SourceManager. -class PresumedLoc { - const char *Filename; - unsigned Line, Col; - SourceLocation IncludeLoc; -public: - PresumedLoc() : Filename(nullptr) {} - PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) - : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { - } - - /// \brief Return true if this object is invalid or uninitialized. - /// - /// This occurs when created with invalid source locations or when walking - /// off the top of a \#include stack. - bool isInvalid() const { return Filename == nullptr; } - bool isValid() const { return Filename != nullptr; } - - /// \brief Return the presumed filename of this location. - /// - /// This can be affected by \#line etc. - const char *getFilename() const { assert(isValid()); return Filename; } - - /// \brief Return the presumed line number of this location. - /// - /// This can be affected by \#line etc. - unsigned getLine() const { assert(isValid()); return Line; } - - /// \brief Return the presumed column number of this location. - /// - /// This cannot be affected by \#line, but is packaged here for convenience. - unsigned getColumn() const { assert(isValid()); return Col; } - - /// \brief Return the presumed include location of this location. - /// - /// This can be affected by GNU linemarker directives. - SourceLocation getIncludeLoc() const { assert(isValid()); return IncludeLoc; } -}; } // end namespace clang diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 5e01f6416748..ed3f8dfa86e7 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -80,9 +80,19 @@ namespace SrcMgr { /// system_header is seen or in various other cases. /// enum CharacteristicKind { - C_User, C_System, C_ExternCSystem + C_User, C_System, C_ExternCSystem, C_User_ModuleMap, C_System_ModuleMap }; + /// Determine whether a file / directory characteristic is for system code. + inline bool isSystem(CharacteristicKind CK) { + return CK != C_User && CK != C_User_ModuleMap; + } + + /// Determine whether a file characteristic is for a module map. + inline bool isModuleMap(CharacteristicKind CK) { + return CK == C_User_ModuleMap || CK == C_System_ModuleMap; + } + /// \brief One instance of this struct is kept for every file loaded or used. /// /// This object owns the MemoryBuffer object. @@ -251,12 +261,14 @@ namespace SrcMgr { /// preprocessing of this \#include, including this SLocEntry. /// /// Zero means the preprocessor didn't provide such info for this SLocEntry. - unsigned NumCreatedFIDs; + unsigned NumCreatedFIDs : 31; - /// \brief Contains the ContentCache* and the bits indicating the - /// characteristic of the file and whether it has \#line info, all - /// bitmangled together. - uintptr_t Data; + /// \brief Whether this FileInfo has any \#line directives. + unsigned HasLineDirectives : 1; + + /// \brief The content cache and the characteristic of the file. + llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind> + ContentAndKind; friend class clang::SourceManager; friend class clang::ASTWriter; @@ -269,10 +281,9 @@ namespace SrcMgr { FileInfo X; X.IncludeLoc = IL.getRawEncoding(); X.NumCreatedFIDs = 0; - X.Data = (uintptr_t)Con; - assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned"); - assert((unsigned)FileCharacter < 4 && "invalid file character"); - X.Data |= (unsigned)FileCharacter; + X.HasLineDirectives = false; + X.ContentAndKind.setPointer(Con); + X.ContentAndKind.setInt(FileCharacter); return X; } @@ -280,22 +291,22 @@ namespace SrcMgr { return SourceLocation::getFromRawEncoding(IncludeLoc); } - const ContentCache* getContentCache() const { - return reinterpret_cast<const ContentCache*>(Data & ~uintptr_t(7)); + const ContentCache *getContentCache() const { + return ContentAndKind.getPointer(); } /// \brief Return whether this is a system header or not. CharacteristicKind getFileCharacteristic() const { - return (CharacteristicKind)(Data & 3); + return ContentAndKind.getInt(); } /// \brief Return true if this FileID has \#line directives in it. - bool hasLineDirectives() const { return (Data & 4) != 0; } + bool hasLineDirectives() const { return HasLineDirectives; } /// \brief Set the flag that indicates that this FileID has /// line table entries associated with it. void setHasLineDirectives() { - Data |= 4; + HasLineDirectives = true; } }; @@ -407,6 +418,8 @@ namespace SrcMgr { }; public: + SLocEntry() : Offset(), IsExpansion(), File() {} + unsigned getOffset() const { return Offset; } bool isExpansion() const { return IsExpansion; } @@ -789,9 +802,8 @@ public: FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID = 0, unsigned LoadedOffset = 0) { - const SrcMgr::ContentCache * - IR = getOrCreateContentCache(SourceFile, - /*isSystemFile=*/FileCharacter != SrcMgr::C_User); + const SrcMgr::ContentCache *IR = + getOrCreateContentCache(SourceFile, isSystem(FileCharacter)); assert(IR && "getOrCreateContentCache() cannot return NULL"); return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset); } @@ -1360,7 +1372,7 @@ public: /// \brief Returns if a SourceLocation is in a system header. bool isInSystemHeader(SourceLocation Loc) const { - return getFileCharacteristic(Loc) != SrcMgr::C_User; + return isSystem(getFileCharacteristic(Loc)); } /// \brief Returns if a SourceLocation is in an "extern C" system header. @@ -1477,6 +1489,17 @@ public: /// \returns true if LHS source location comes before RHS, false otherwise. bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; + /// \brief Determines whether the two decomposed source location is in the + /// same translation unit. As a byproduct, it also calculates the order + /// of the source locations in case they are in the same TU. + /// + /// \returns Pair of bools the first component is true if the two locations + /// are in the same TU. The second bool is true if the first is true + /// and \p LOffs is before \p ROffs. + std::pair<bool, bool> + isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs, + std::pair<FileID, unsigned> &ROffs) const; + /// \brief Determines the order of 2 source locations in the "source location /// address space". bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const { diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index 5d45e162d9f6..8f4f5e9a74dd 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -150,6 +150,16 @@ namespace clang { }; } + /// \brief Nios2 builtins + namespace Nios2 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsNios2.def" + LastTSBuiltin + }; + } + /// \brief MIPS builtins namespace Mips { enum { diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 6ca1ba39c8fb..9bb19c7b79df 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -18,6 +18,7 @@ #include <string> #include <vector> #include "clang/Basic/OpenCLOptions.h" +#include "llvm/Target/TargetOptions.h" namespace clang { @@ -41,7 +42,7 @@ public: std::string ABI; /// The EABI version to use - std::string EABIVersion; + llvm::EABI EABIVersion; /// If given, the version string of the linker in use. std::string LinkerVersion; diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h index 6ac52ed6b5e1..cc839d789e7f 100644 --- a/include/clang/Basic/Visibility.h +++ b/include/clang/Basic/Visibility.h @@ -75,6 +75,9 @@ public: static LinkageInfo none() { return LinkageInfo(NoLinkage, DefaultVisibility, false); } + static LinkageInfo visible_none() { + return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false); + } Linkage getLinkage() const { return (Linkage)linkage_; } Visibility getVisibility() const { return (Visibility)visibility_; } diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index c478cfc7833e..205f36b723c8 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -145,7 +145,7 @@ def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">, HelpText<"DWARF debug sections compression">; -def compress_debug_sections_EQ : Flag<["-"], "compress-debug-sections=">, +def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">, HelpText<"DWARF debug sections compression type">; def mno_exec_stack : Flag<["-"], "mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; @@ -268,8 +268,6 @@ def vectorize_loops : Flag<["-"], "vectorize-loops">, HelpText<"Run the Loop vectorization passes">; def vectorize_slp : Flag<["-"], "vectorize-slp">, HelpText<"Run the SLP vectorization passes">; -def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">, - HelpText<"Run the BB vectorization passes">; def dependent_lib : Joined<["--"], "dependent-lib=">, HelpText<"Add dependent library">; def linker_option : Joined<["--"], "linker-option=">, @@ -323,6 +321,10 @@ def flto_unit: Flag<["-"], "flto-unit">, def fno_lto_unit: Flag<["-"], "fno-lto-unit">; def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">, HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">; +def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">, + HelpText<"Prints debug information for the new pass manager">; +def fno_debug_pass_manager : Flag<["-"], "fno-debug-pass-manager">, + HelpText<"Disables debug printing for the new pass manager">; //===----------------------------------------------------------------------===// // Dependency Output Options @@ -568,6 +570,9 @@ def find_pch_source_EQ : Joined<["-"], "find-pch-source=">, def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">, HelpText<"Disable inclusion of timestamp in precompiled headers">; +def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">, + HelpText<"Aligned allocation/deallocation functions are unavailable">; + //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===// diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 114e0b33c75a..036b04605ac7 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -105,10 +105,13 @@ class Compilation { /// Whether we're compiling for diagnostic purposes. bool ForDiagnostics; + /// Whether an error during the parsing of the input args. + bool ContainsError; + public: Compilation(const Driver &D, const ToolChain &DefaultToolChain, llvm::opt::InputArgList *Args, - llvm::opt::DerivedArgList *TranslatedArgs); + llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError); ~Compilation(); const Driver &getDriver() const { return TheDriver; } @@ -275,6 +278,9 @@ public: /// Return true if we're compiling for diagnostics. bool isForDiagnostics() const { return ForDiagnostics; } + /// Return whether an error during the parsing of the input args. + bool containsError() const { return ContainsError; } + /// Redirect - Redirect output of this compilation. Can only be done once. /// /// \param Redirects - array of pointers to paths. The array diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 1009754a15d5..5a087eea1b4e 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -341,7 +341,8 @@ public: /// ParseArgStrings - Parse the given list of strings into an /// ArgList. - llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args); + llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args, + bool &ContainsError); /// BuildInputs - Construct the list of inputs and their types from /// the given arguments. diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 68b331fed2bd..b65b984731f6 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -723,6 +723,9 @@ def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-sourc HelpText<"Print source range spans in numeric form">; def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">; +def fdiagnostics_hotness_threshold_EQ : Joined<["-"], "fdiagnostics-hotness-threshold=">, + Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">, + HelpText<"Prevent optimization remarks from being output if they do not have at least this profile count">; def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">, @@ -1405,9 +1408,6 @@ def : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>; def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group<f_Group>, HelpText<"Enable the superword-level parallelism vectorization passes">; def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>; -def fslp_vectorize_aggressive : Flag<["-"], "fslp-vectorize-aggressive">, Group<f_Group>, - HelpText<"Enable the BB vectorization passes">; -def fno_slp_vectorize_aggressive : Flag<["-"], "fno-slp-vectorize-aggressive">, Group<f_Group>; def : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>; def : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>; def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">, diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index c1b62477ed1c..ee24c55fef61 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -717,7 +717,29 @@ struct FormatStyle { /// } /// \endcode /// - bool SplitEmptyFunctionBody; + bool SplitEmptyFunction; + /// \brief If ``false``, empty record (e.g. class, struct or union) body + /// can be put on a single line. This option is used only if the opening + /// brace of the record has already been wrapped, i.e. the `AfterClass` + /// (for classes) brace wrapping mode is set. + /// \code + /// class Foo vs. class Foo + /// {} { + /// } + /// \endcode + /// + bool SplitEmptyRecord; + /// \brief If ``false``, empty namespace body can be put on a single line. + /// This option is used only if the opening brace of the namespace has + /// already been wrapped, i.e. the `AfterNamespace` brace wrapping mode is + /// set. + /// \code + /// namespace Foo vs. namespace Foo + /// {} { + /// } + /// \endcode + /// + bool SplitEmptyNamespace; }; /// \brief Control of individual brace wrapping cases. @@ -966,7 +988,7 @@ struct FormatStyle { /// IncludeCategories: /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/' /// Priority: 2 - /// - Regex: '^(<|"(gtest|isl|json)/)' + /// - Regex: '^(<|"(gtest|gmock|isl|json)/)' /// Priority: 3 /// - Regex: '.*' /// Priority: 1 diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 2950c31c2d3d..1ac4f07a3549 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -628,6 +628,15 @@ public: IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool CaptureDiagnostics, bool UserFilesAreVolatile); + enum WhatToLoad { + /// Load options and the preprocessor state. + LoadPreprocessorOnly, + /// Load the AST, but do not restore Sema state. + LoadASTOnly, + /// Load everything, including Sema. + LoadEverything + }; + /// \brief Create a ASTUnit from an AST file. /// /// \param Filename - The AST file to load. @@ -640,7 +649,7 @@ public: /// \returns - The initialized ASTUnit or null if the AST failed to load. static std::unique_ptr<ASTUnit> LoadFromASTFile( const std::string &Filename, const PCHContainerReader &PCHContainerRdr, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool UseDebugInfo = false, bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None, bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index f3deb05ec6df..238bb231bdf5 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -57,6 +57,8 @@ CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0 CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental ///< pass manager. +CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new + ///< pass manager. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what @@ -177,7 +179,6 @@ CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled. CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled. CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns. CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables. -CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer. CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. @@ -260,6 +261,10 @@ VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0) /// Whether to report the hotness of the code region for optimization remarks. CODEGENOPT(DiagnosticsWithHotness, 1, 0) +/// The minimum hotness value a diagnostic needs in order to be included in +/// optimization diagnostics. +VALUE_CODEGENOPT(DiagnosticsHotnessThreshold, 32, 0) + /// Whether copy relocations support is available when building as PIE. CODEGENOPT(PIECopyRelocations, 1, 0) diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index 2588feb2b87d..e453d7db624c 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -70,33 +70,27 @@ protected: DiagnosticOptions *DiagOpts); virtual ~DiagnosticRenderer(); - - virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, + + virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, - const SourceManager *SM, DiagOrStoredDiag Info) = 0; - - virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + + virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) = 0; + ArrayRef<CharSourceRange> Ranges) = 0; - virtual void emitCodeContext(SourceLocation Loc, + virtual void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) = 0; - - virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM) = 0; - virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) = 0; - virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) = 0; + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints) = 0; + + virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0; + virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) = 0; + virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) = 0; virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} @@ -106,25 +100,21 @@ protected: private: void emitBasicNote(StringRef Message); - void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, - DiagnosticsEngine::Level Level, const SourceManager &SM); - void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); - void emitImportStack(SourceLocation Loc, const SourceManager &SM); - void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, - const SourceManager &SM); + void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level); + void emitIncludeStackRecursively(FullSourceLoc Loc); + void emitImportStack(FullSourceLoc Loc); + void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName); void emitModuleBuildStack(const SourceManager &SM); - void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints, - const SourceManager &SM); - void emitSingleMacroExpansion(SourceLocation Loc, + void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints); + void emitSingleMacroExpansion(FullSourceLoc Loc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM); - void emitMacroExpansions(SourceLocation Loc, - DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges); + void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM); + ArrayRef<FixItHint> Hints); + public: /// \brief Emit a diagnostic. /// @@ -138,12 +128,9 @@ public: /// \param Message The diagnostic message to emit. /// \param Ranges The underlined ranges for this code snippet. /// \param FixItHints The FixIt hints active for this diagnostic. - /// \param SM The SourceManager; will be null if the diagnostic came from the - /// frontend, thus \p Loc will be invalid. - void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, + void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, - const SourceManager *SM, DiagOrStoredDiag D = (Diagnostic *)nullptr); void emitStoredDiagnostic(StoredDiagnostic &Diag); @@ -159,19 +146,15 @@ public: ~DiagnosticNoteRenderer() override; - void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM) override; + void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override; - void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; - void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; - virtual void emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) = 0; + virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0; }; } // end clang namespace #endif diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index 9b108c28bd1c..1bbfe9fa02e3 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -75,44 +75,35 @@ public: unsigned Columns, bool ShowColors); protected: - void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, + void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, - const SourceManager *SM, DiagOrStoredDiag D) override; - void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) override; - - void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) override { - emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM); + ArrayRef<CharSourceRange> Ranges) override; + + void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints) override { + emitSnippetAndCaret(Loc, Level, Ranges, Hints); } - void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM) override; + void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override; - void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; - void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; private: void emitFilename(StringRef Filename, const SourceManager &SM); - void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM); + void emitSnippetAndCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints); void emitSnippet(StringRef SourceLine); diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 0ee46846c804..8ccc31982dab 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -184,10 +184,11 @@ createChainedIncludesSource(CompilerInstance &CI, /// /// \return A CompilerInvocation, or 0 if none was built for the given /// argument vector. -std::unique_ptr<CompilerInvocation> -createInvocationFromCommandLine(ArrayRef<const char *> Args, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags = - IntrusiveRefCntPtr<DiagnosticsEngine>()); +std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine( + ArrayRef<const char *> Args, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags = + IntrusiveRefCntPtr<DiagnosticsEngine>(), + IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr); /// Return the value of the last argument as an integer, or a default. If Diags /// is non-null, emits an error if the argument is given, but non-integral. diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index ee17dcbb8b5a..1b7f80c87ff1 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -47,7 +47,7 @@ struct HeaderFileInfo { /// whether it is C++ clean or not. This can be set by the include paths or /// by \#pragma gcc system_header. This is an instance of /// SrcMgr::CharacteristicKind. - unsigned DirInfo : 2; + unsigned DirInfo : 3; /// \brief Whether this header file info was supplied by an external source, /// and has not changed since. diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index 904be792b2a9..f96af665b157 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -36,7 +36,7 @@ class PTHLexer : public PreprocessorLexer { const unsigned char* LastHashTokPtr; /// PPCond - Pointer to a side table in the PTH file that provides a - /// a consise summary of the preproccessor conditional block structure. + /// a concise summary of the preprocessor conditional block structure. /// This is used to perform quick skipping of conditional blocks. const unsigned char* PPCond; diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index 9134ddf9198c..ea32997d4066 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -18,6 +18,8 @@ #include "clang/AST/DeclCXX.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/Optional.h" + namespace clang { /// @brief Represents the results of name lookup. @@ -273,7 +275,7 @@ public: /// declarations, such as those in modules that have not yet been imported. bool isHiddenDeclarationVisible(NamedDecl *ND) const { return AllowHidden || - (isForRedeclaration() && ND->isExternallyVisible()); + (isForRedeclaration() && ND->hasExternalFormalLinkage()); } /// Sets whether tag declarations should be hidden by non-tag @@ -465,7 +467,7 @@ public: Paths = nullptr; } } else { - AmbiguityKind SavedAK; + llvm::Optional<AmbiguityKind> SavedAK; bool WasAmbiguous = false; if (ResultKind == Ambiguous) { SavedAK = Ambiguity; @@ -479,7 +481,7 @@ public: if (ResultKind == Ambiguous) { (void)WasAmbiguous; assert(WasAmbiguous); - Ambiguity = SavedAK; + Ambiguity = SavedAK.getValue(); } else if (Paths) { deletePaths(Paths); Paths = nullptr; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 02c133d1c4fc..95134d52f873 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1542,6 +1542,10 @@ public: bool hasVisibleMergedDefinition(NamedDecl *Def); + /// Determine if \p D and \p Suggested have a structurally compatible + /// layout as described in C11 6.2.7/1. + bool hasStructuralCompatLayout(Decl *D, Decl *Suggested); + /// Determine if \p D has a visible definition. If not, suggest a declaration /// that should be made visible to expose the definition. bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, @@ -1629,9 +1633,13 @@ public: // struct SkipBodyInfo { - SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {} + SkipBodyInfo() + : ShouldSkip(false), CheckSameAsPrevious(false), Previous(nullptr), + New(nullptr) {} bool ShouldSkip; + bool CheckSameAsPrevious; NamedDecl *Previous; + NamedDecl *New; }; DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); @@ -2145,13 +2153,11 @@ public: }; Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, - SourceLocation ModulePrivateLoc, - MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl, bool &IsDependent, - SourceLocation ScopedEnumKWLoc, + SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, AttributeList *Attr, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, + bool &IsDependent, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody = nullptr); @@ -2219,6 +2225,12 @@ public: /// struct, or union). void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); + /// Perform ODR-like check for C/ObjC when merging tag types from modules. + /// Differently from C++, actually parse the body and reject / error out + /// in case of a structural mismatch. + bool ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev, + SkipBodyInfo &SkipBody); + typedef void *SkippedDefinitionContext; /// \brief Invoked when we enter a tag definition that we're skipping. @@ -2272,8 +2284,8 @@ public: Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attrs, - SourceLocation EqualLoc, Expr *Val); + AttributeList *Attrs, SourceLocation EqualLoc, + Expr *Val); void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, Decl *EnumDecl, ArrayRef<Decl *> Elements, @@ -3233,7 +3245,7 @@ public: void ProcessPragmaWeak(Scope *S, Decl *D); // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); - // Helper for delayed proccessing of attributes. + // Helper for delayed processing of attributes. void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList); void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, bool IncludeCXX11Attributes = true); @@ -8432,7 +8444,7 @@ public: /// is disabled due to required OpenCL extensions being disabled. If so, /// emit diagnostics. /// \return true if type is disabled. - bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E); + bool checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E); //===--------------------------------------------------------------------===// // OpenMP directives and clauses. @@ -10276,6 +10288,7 @@ private: void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); void CheckBoolLikeConversion(Expr *E, SourceLocation CC); + void CheckForIntOverflow(Expr *E); void CheckUnsequencedOperations(Expr *E); /// \brief Perform semantic checks on a completed expression. This will either diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 737f6fb3d413..eafa05175832 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -400,7 +400,7 @@ private: Preprocessor &PP; /// \brief The AST context into which we'll read the AST files. - ASTContext &Context; + ASTContext *ContextObj = nullptr; /// \brief The AST consumer. ASTConsumer *Consumer = nullptr; @@ -1146,6 +1146,7 @@ private: time_t StoredTime; bool Overridden; bool Transient; + bool TopLevelModuleMap; }; /// \brief Reads the stored information about an input file. @@ -1386,7 +1387,7 @@ public: /// precompiled header will be loaded. /// /// \param Context the AST context that this precompiled header will be - /// loaded into. + /// loaded into, if any. /// /// \param PCHContainerRdr the PCHContainerOperations to use for loading and /// creating modules. @@ -1418,7 +1419,7 @@ public: /// /// \param ReadTimer If non-null, a timer used to track the time spent /// deserializing. - ASTReader(Preprocessor &PP, ASTContext &Context, + ASTReader(Preprocessor &PP, ASTContext *Context, const PCHContainerReader &PCHContainerRdr, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, StringRef isysroot = "", bool DisableValidation = false, @@ -2207,7 +2208,10 @@ public: void completeVisibleDeclsMap(const DeclContext *DC) override; /// \brief Retrieve the AST context that this AST reader supplements. - ASTContext &getContext() { return Context; } + ASTContext &getContext() { + assert(ContextObj && "requested AST context when not loading AST"); + return *ContextObj; + } // \brief Contains the IDs for declarations that were requested before we have // access to a Sema object. @@ -2249,6 +2253,12 @@ public: llvm::function_ref<void(const serialization::InputFile &IF, bool isSystem)> Visitor); + /// Visit all the top-level module maps loaded when building the given module + /// file. + void visitTopLevelModuleMaps(serialization::ModuleFile &MF, + llvm::function_ref< + void(const FileEntry *)> Visitor); + bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; } }; diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 4171c685cb98..82ab720af8dc 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -38,6 +38,11 @@ def CoreAlpha : Package<"core">, InPackage<Alpha>, Hidden; // default. Such checkers belong in the alpha package. def OptIn : Package<"optin">; +// In the Portability package reside checkers for finding code that relies on +// implementation-defined behavior. Such checks are wanted for cross-platform +// development, but unwanted for developers who target only a single platform. +def PortabilityOptIn : Package<"portability">, InPackage<OptIn>; + def Nullability : Package<"nullability">; def Cplusplus : Package<"cplusplus">; @@ -416,7 +421,7 @@ def GenericTaintChecker : Checker<"TaintPropagation">, let ParentPackage = Unix in { -def UnixAPIChecker : Checker<"API">, +def UnixAPIMisuseChecker : Checker<"API">, HelpText<"Check calls to various UNIX/Posix functions">, DescFile<"UnixAPIChecker.cpp">; @@ -754,3 +759,14 @@ def CloneChecker : Checker<"CloneChecker">, } // end "clone" +//===----------------------------------------------------------------------===// +// Portability checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = PortabilityOptIn in { + +def UnixAPIPortabilityChecker : Checker<"UnixAPI">, + HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">, + DescFile<"UnixAPIChecker.cpp">; + +} // end optin.portability diff --git a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h new file mode 100644 index 000000000000..099eaca6c42a --- /dev/null +++ b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h @@ -0,0 +1,70 @@ +//===--- RenamingAction.h - Clang refactoring library ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides an action to rename every symbol at a point. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H + +#include "clang/Tooling/Refactoring.h" + +namespace clang { +class ASTConsumer; +class CompilerInstance; + +namespace tooling { + +class RenamingAction { +public: + RenamingAction(const std::vector<std::string> &NewNames, + const std::vector<std::string> &PrevNames, + const std::vector<std::vector<std::string>> &USRList, + std::map<std::string, tooling::Replacements> &FileToReplaces, + bool PrintLocations = false) + : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList), + FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {} + + std::unique_ptr<ASTConsumer> newASTConsumer(); + +private: + const std::vector<std::string> &NewNames, &PrevNames; + const std::vector<std::vector<std::string>> &USRList; + std::map<std::string, tooling::Replacements> &FileToReplaces; + bool PrintLocations; +}; + +/// Rename all symbols identified by the given USRs. +class QualifiedRenamingAction { +public: + QualifiedRenamingAction( + const std::vector<std::string> &NewNames, + const std::vector<std::vector<std::string>> &USRList, + std::map<std::string, tooling::Replacements> &FileToReplaces) + : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {} + + std::unique_ptr<ASTConsumer> newASTConsumer(); + +private: + /// New symbol names. + const std::vector<std::string> &NewNames; + + /// A list of USRs. Each element represents USRs of a symbol being renamed. + const std::vector<std::vector<std::string>> &USRList; + + /// A file path to replacements map. + std::map<std::string, tooling::Replacements> &FileToReplaces; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H diff --git a/include/clang/Tooling/Refactoring/Rename/USRFinder.h b/include/clang/Tooling/Refactoring/Rename/USRFinder.h new file mode 100644 index 000000000000..28d541af43c0 --- /dev/null +++ b/include/clang/Tooling/Refactoring/Rename/USRFinder.h @@ -0,0 +1,84 @@ +//===--- USRFinder.h - Clang refactoring library --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Methods for determining the USR of a symbol at a location in source +/// code. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDER_H +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDER_H + +#include "clang/AST/AST.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include <string> +#include <vector> + +using namespace llvm; +using namespace clang::ast_matchers; + +namespace clang { + +class ASTContext; +class Decl; +class SourceLocation; +class NamedDecl; + +namespace tooling { + +// Given an AST context and a point, returns a NamedDecl identifying the symbol +// at the point. Returns null if nothing is found at the point. +const NamedDecl *getNamedDeclAt(const ASTContext &Context, + const SourceLocation Point); + +// Given an AST context and a fully qualified name, returns a NamedDecl +// identifying the symbol with a matching name. Returns null if nothing is +// found for the name. +const NamedDecl *getNamedDeclFor(const ASTContext &Context, + const std::string &Name); + +// Converts a Decl into a USR. +std::string getUSRForDecl(const Decl *Decl); + +// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead. +class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback { +public: + explicit NestedNameSpecifierLocFinder(ASTContext &Context) + : Context(Context) {} + + std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() { + addMatchers(); + Finder.matchAST(Context); + return Locations; + } + +private: + void addMatchers() { + const auto NestedNameSpecifierLocMatcher = + nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc"); + Finder.addMatcher(NestedNameSpecifierLocMatcher, this); + } + + void run(const MatchFinder::MatchResult &Result) override { + const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>( + "nestedNameSpecifierLoc"); + Locations.push_back(*NNS); + } + + ASTContext &Context; + std::vector<NestedNameSpecifierLoc> Locations; + MatchFinder Finder; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDER_H diff --git a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h new file mode 100644 index 000000000000..8aafee95bc09 --- /dev/null +++ b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h @@ -0,0 +1,54 @@ +//===--- USRFindingAction.h - Clang refactoring library -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides an action to find all relevant USRs at a point. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDING_ACTION_H +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDING_ACTION_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" + +#include <string> +#include <vector> + +namespace clang { +class ASTConsumer; +class CompilerInstance; +class NamedDecl; + +namespace tooling { + +struct USRFindingAction { + USRFindingAction(ArrayRef<unsigned> SymbolOffsets, + ArrayRef<std::string> QualifiedNames, bool Force) + : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames), + ErrorOccurred(false), Force(Force) {} + std::unique_ptr<ASTConsumer> newASTConsumer(); + + ArrayRef<std::string> getUSRSpellings() { return SpellingNames; } + ArrayRef<std::vector<std::string>> getUSRList() { return USRList; } + bool errorOccurred() { return ErrorOccurred; } + +private: + std::vector<unsigned> SymbolOffsets; + std::vector<std::string> QualifiedNames; + std::vector<std::string> SpellingNames; + std::vector<std::vector<std::string>> USRList; + bool ErrorOccurred; + bool Force; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_FINDING_ACTION_H diff --git a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h new file mode 100644 index 000000000000..733ea1a6ac9e --- /dev/null +++ b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h @@ -0,0 +1,49 @@ +//===--- USRLocFinder.h - Clang refactoring library -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides functionality for finding all instances of a USR in a given +/// AST. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_LOC_FINDER_H +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_LOC_FINDER_H + +#include "clang/AST/AST.h" +#include "clang/Tooling/Core/Replacement.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace clang { +namespace tooling { + +/// Create atomic changes for renaming all symbol references which are +/// identified by the USRs set to a given new name. +/// +/// \param USRs The set containing USRs of a particular old symbol. +/// \param NewName The new name to replace old symbol name. +/// \param TranslationUnitDecl The translation unit declaration. +/// +/// \return Atomic changes for renaming. +std::vector<tooling::AtomicChange> +createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs, + llvm::StringRef NewName, Decl *TranslationUnitDecl); + +// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree! +std::vector<SourceLocation> +getLocationsOfUSRs(const std::vector<std::string> &USRs, + llvm::StringRef PrevName, Decl *Decl); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_USR_LOC_FINDER_H diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap index 3b4238110026..f7e338d93399 100644 --- a/include/clang/module.modulemap +++ b/include/clang/module.modulemap @@ -33,6 +33,7 @@ module Clang_Basic { textual header "Basic/BuiltinsLe64.def" textual header "Basic/BuiltinsMips.def" textual header "Basic/BuiltinsNEON.def" + textual header "Basic/BuiltinsNios2.def" textual header "Basic/BuiltinsNVPTX.def" textual header "Basic/BuiltinsPPC.def" textual header "Basic/BuiltinsSystemZ.def" @@ -132,9 +133,10 @@ module Clang_StaticAnalyzer_Frontend { module Clang_Tooling { requires cplusplus umbrella "Tooling" module * { export * } - // FIXME: Exclude this header to avoid pulling all of the AST matchers + // FIXME: Exclude these headers to avoid pulling all of the AST matchers // library into clang-format. Due to inline key functions in the headers, // importing the AST matchers library gives a link dependency on the AST // matchers (and thus the AST), which clang-format should not have. exclude header "Tooling/RefactoringCallbacks.h" + exclude header "Tooling/Refactoring/Rename/USRFinder.h" } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index fabfdc9ef7e5..a2ff176df11f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -5990,9 +5990,19 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, // compatibility with GCC, although providing it breaks anything that // actually uses runtime introspection and wants to work on both runtimes... if (Ctx->getLangOpts().ObjCRuntime.isGNUFamily()) { - const RecordDecl *RD = FD->getParent(); - const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); - S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); + uint64_t Offset; + + if (const auto *IVD = dyn_cast<ObjCIvarDecl>(FD)) { + Offset = Ctx->lookupFieldBitOffset(IVD->getContainingInterface(), nullptr, + IVD); + } else { + const RecordDecl *RD = FD->getParent(); + const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); + Offset = RL.getFieldOffset(FD->getFieldIndex()); + } + + S += llvm::utostr(Offset); + if (const EnumType *ET = T->getAs<EnumType>()) S += ObjCEncodingForEnumType(Ctx, ET); else { diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index eff1aa5e323d..ea7faab767ed 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -735,13 +735,28 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // Check for equivalent field names. IdentifierInfo *Name1 = Field1->getIdentifier(); IdentifierInfo *Name2 = Field2->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2)) + if (!::IsStructurallyEquivalent(Name1, Name2)) { + if (Context.Complain) { + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) + << Context.ToCtx.getTypeDeclType(Owner2); + Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) + << Field2->getDeclName(); + Context.Diag1(Field1->getLocation(), diag::note_odr_field_name) + << Field1->getDeclName(); + } return false; + } if (!IsStructurallyEquivalent(Context, Field1->getType(), Field2->getType())) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); @@ -753,7 +768,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field1->isBitField() != Field2->isBitField()) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(Owner2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(Owner2); if (Field1->isBitField()) { Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) @@ -780,7 +798,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Bits1 != Bits2) { if (Context.Complain) { Context.Diag2(Owner2->getLocation(), - diag::warn_odr_tag_type_inconsistent) + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) << Field2->getDeclName() << Field2->getType() << Bits2; @@ -799,7 +819,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { if (D1->isUnion() != D2->isUnion()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here) << D1->getDeclName() << (unsigned)D1->getTagKind(); @@ -927,7 +950,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Field1 != Field1End; ++Field1, ++Field2) { if (Field2 == Field2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(Field1->getLocation(), diag::note_odr_field) << Field1->getDeclName() << Field1->getType(); @@ -942,7 +968,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field2 != Field2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); @@ -964,7 +993,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, EC1 != EC1End; ++EC1, ++EC2) { if (EC2 == EC2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) << EC1->getDeclName() << EC1->getInitVal().toString(10); @@ -978,7 +1010,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!llvm::APSInt::isSameValue(Val1, Val2) || !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) << EC2->getDeclName() << EC2->getInitVal().toString(10); @@ -991,7 +1026,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (EC2 != EC2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.ErrorOnTagTypeMismatch + ? diag::err_odr_tag_type_inconsistent + : diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) << EC2->getDeclName() << EC2->getInitVal().toString(10); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 9862f4f26473..267c6992af89 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1251,7 +1251,9 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, case Decl::EnumConstant: // C++ [basic.link]p4: an enumerator has the linkage of its enumeration. - return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation); + if (D->getASTContext().getLangOpts().CPlusPlus) + return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation); + return LinkageInfo::visible_none(); case Decl::Typedef: case Decl::TypeAlias: @@ -2630,7 +2632,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); } -bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { +bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const { if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) return false; if (getDeclName().getCXXOverloadedOperator() != OO_New && @@ -2676,8 +2678,11 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { // In C++17, the next parameter can be a 'std::align_val_t' for aligned // new/delete. - if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) + if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) { + if (IsAligned) + *IsAligned = true; Consume(); + } // Finally, if this is not a sized delete, the final parameter can // be a 'const std::nothrow_t&'. diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 9f87fe12a9cd..07d128ba555b 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1417,11 +1417,8 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { Context.getCanonicalType(ClassType)); DeclContext::lookup_result R = lookup(Name); - if (R.empty()) - return nullptr; - CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front()); - return Dtor; + return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front()); } bool CXXRecordDecl::isAnyDestructorNoReturn() const { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c21cd3f65bd4..afc7fa8ea094 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1641,25 +1641,32 @@ const char *CastExpr::getCastKindName() const { llvm_unreachable("Unhandled cast kind!"); } +namespace { + Expr *skipImplicitTemporary(Expr *expr) { + // Skip through reference binding to temporary. + if (MaterializeTemporaryExpr *Materialize + = dyn_cast<MaterializeTemporaryExpr>(expr)) + expr = Materialize->GetTemporaryExpr(); + + // Skip any temporary bindings; they're implicit. + if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr)) + expr = Binder->getSubExpr(); + + return expr; + } +} + Expr *CastExpr::getSubExprAsWritten() { Expr *SubExpr = nullptr; CastExpr *E = this; do { - SubExpr = E->getSubExpr(); + SubExpr = skipImplicitTemporary(E->getSubExpr()); - // Skip through reference binding to temporary. - if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(SubExpr)) - SubExpr = Materialize->GetTemporaryExpr(); - - // Skip any temporary bindings; they're implicit. - if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr)) - SubExpr = Binder->getSubExpr(); - // Conversions by constructor and conversion functions have a // subexpression describing the call; strip it off. if (E->getCastKind() == CK_ConstructorConversion) - SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0); + SubExpr = + skipImplicitTemporary(cast<CXXConstructExpr>(SubExpr)->getArg(0)); else if (E->getCastKind() == CK_UserDefinedConversion) { assert((isa<CXXMemberCallExpr>(SubExpr) || isa<BlockExpr>(SubExpr)) && diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 768947d00ac4..e836135cf2f9 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -6226,10 +6226,6 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { // the initializer list. ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; - if (Init->isValueDependent()) { - Success = false; - continue; - } // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, @@ -9940,8 +9936,7 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { } static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, - const ASTContext &Ctx, bool &IsConst, - bool IsCheckingForOverflow) { + const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(Exp)) { @@ -9962,7 +9957,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, // performance problems. Only do so in C++11 for now. if (Exp->isRValue() && (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus11 && !IsCheckingForOverflow) { + !Ctx.getLangOpts().CPlusPlus11) { IsConst = false; return true; } @@ -9977,7 +9972,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, /// will be applied to the result. bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { bool IsConst; - if (FastEvaluateAsRValue(this, Result, Ctx, IsConst, false)) + if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) return IsConst; EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); @@ -10102,7 +10097,7 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EvalResult; - if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst, true)) { + if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); (void)::EvaluateAsRValue(Info, this, EvalResult.Val); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index cc7a6941f63a..3a899bdbb6d2 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -966,16 +966,71 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { } if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = - Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle a local inside this block yet"); - Diags.Report(BD->getLocation(), DiagID); - - // FIXME: This is completely, utterly, wrong; see ItaniumMangle - // for how this should be done. - Out << "__block_invoke" << Context.getBlockId(BD, false); - Out << '@'; + auto Discriminate = + [](StringRef Name, const unsigned Discriminator, + const unsigned ParameterDiscriminator) -> std::string { + std::string Buffer; + llvm::raw_string_ostream Stream(Buffer); + Stream << Name; + if (Discriminator) + Stream << '_' << Discriminator; + if (ParameterDiscriminator) + Stream << '_' << ParameterDiscriminator; + return Stream.str(); + }; + + unsigned Discriminator = BD->getBlockManglingNumber(); + if (!Discriminator) + Discriminator = Context.getBlockId(BD, /*Local=*/false); + + // Mangle the parameter position as a discriminator to deal with unnamed + // parameters. Rather than mangling the unqualified parameter name, + // always use the position to give a uniform mangling. + unsigned ParameterDiscriminator = 0; + if (const auto *MC = BD->getBlockManglingContextDecl()) + if (const auto *P = dyn_cast<ParmVarDecl>(MC)) + if (const auto *F = dyn_cast<FunctionDecl>(P->getDeclContext())) + ParameterDiscriminator = + F->getNumParams() - P->getFunctionScopeIndex(); + + DC = getEffectiveDeclContext(BD); + + Out << '?'; + mangleSourceName(Discriminate("_block_invoke", Discriminator, + ParameterDiscriminator)); + // If we have a block mangling context, encode that now. This allows us + // to discriminate between named static data initializers in the same + // scope. This is handled differently from parameters, which use + // positions to discriminate between multiple instances. + if (const auto *MC = BD->getBlockManglingContextDecl()) + if (!isa<ParmVarDecl>(MC)) + if (const auto *ND = dyn_cast<NamedDecl>(MC)) + mangleUnqualifiedName(ND); + // MS ABI and Itanium manglings are in inverted scopes. In the case of a + // RecordDecl, mangle the entire scope hierachy at this point rather than + // just the unqualified name to get the ordering correct. + if (const auto *RD = dyn_cast<RecordDecl>(DC)) + mangleName(RD); + else + Out << '@'; + // void __cdecl + Out << "YAX"; + // struct __block_literal * + Out << 'P'; + // __ptr64 + if (PointersAre64Bit) + Out << 'E'; + Out << 'A'; + mangleArtificalTagType(TTK_Struct, + Discriminate("__block_literal", Discriminator, + ParameterDiscriminator)); + Out << "@Z"; + + // If the effective context was a Record, we have fully mangled the + // qualified name and do not need to continue. + if (isa<RecordDecl>(DC)) + break; + continue; } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method); } else if (isa<NamedDecl>(DC)) { diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 05bed658f3fc..3f66e58eb868 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -82,25 +82,13 @@ void ODRHash::AddDeclarationName(DeclarationName Name) { } void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - // Unlike the other pointer handling functions, allow null pointers here. - if (!NNS) { - AddBoolean(false); - return; + assert(NNS && "Expecting non-null pointer."); + const auto *Prefix = NNS->getPrefix(); + AddBoolean(Prefix); + if (Prefix) { + AddNestedNameSpecifier(Prefix); } - - // Skip inlined namespaces. auto Kind = NNS->getKind(); - if (Kind == NestedNameSpecifier::Namespace) { - if (NNS->getAsNamespace()->isInline()) { - return AddNestedNameSpecifier(NNS->getPrefix()); - } - } - - AddBoolean(true); - - // Process prefix - AddNestedNameSpecifier(NNS->getPrefix()); - ID.AddInteger(Kind); switch (Kind) { case NestedNameSpecifier::Identifier: @@ -146,7 +134,10 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) { switch (Kind) { case TemplateArgument::Null: + llvm_unreachable("Expected valid TemplateArgument"); case TemplateArgument::Type: + AddQualType(TA.getAsType()); + break; case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::Integral: @@ -430,8 +421,18 @@ public: Hash.AddQualType(T); } + void AddType(const Type *T) { + Hash.AddBoolean(T); + if (T) { + Hash.AddType(T); + } + } + void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - Hash.AddNestedNameSpecifier(NNS); + Hash.AddBoolean(NNS); + if (NNS) { + Hash.AddNestedNameSpecifier(NNS); + } } void AddIdentifierInfo(const IdentifierInfo *II) { @@ -517,7 +518,13 @@ public: void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); - AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType()); + QualType UnderlyingType = T->getDecl()->getUnderlyingType(); + VisitQualifiers(UnderlyingType.getQualifiers()); + while (const TypedefType *Underlying = + dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) { + UnderlyingType = Underlying->getDecl()->getUnderlyingType(); + } + AddType(UnderlyingType.getTypePtr()); VisitType(T); } diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index cf981be0a4dd..c0b9cadca422 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -3073,6 +3073,41 @@ uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const { return OffsetInBits; } +uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID, + const ObjCImplementationDecl *ID, + const ObjCIvarDecl *Ivar) const { + const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); + + // FIXME: We should eliminate the need to have ObjCImplementationDecl passed + // in here; it should never be necessary because that should be the lexical + // decl context for the ivar. + + // If we know have an implementation (and the ivar is in it) then + // look up in the implementation layout. + const ASTRecordLayout *RL; + if (ID && declaresSameEntity(ID->getClassInterface(), Container)) + RL = &getASTObjCImplementationLayout(ID); + else + RL = &getASTObjCInterfaceLayout(Container); + + // Compute field index. + // + // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is + // implemented. This should be fixed to get the information from the layout + // directly. + unsigned Index = 0; + + for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); + IVD; IVD = IVD->getNextIvar()) { + if (Ivar == IVD) + break; + ++Index; + } + assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); + + return RL->getFieldOffset(Index); +} + /// getObjCLayout - Get or compute information about the layout of the /// given interface. /// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 99a25f342526..f1fbe2806b5d 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -186,7 +186,10 @@ namespace { Hash.AddTemplateName(Name); } void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { - Hash.AddNestedNameSpecifier(NNS); + ID.AddBoolean(NNS); + if (NNS) { + Hash.AddNestedNameSpecifier(NNS); + } } }; } diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp index a58d0465a6f4..89ddbc946a49 100644 --- a/lib/Basic/SourceLocation.cpp +++ b/lib/Basic/SourceLocation.cpp @@ -92,6 +92,76 @@ FullSourceLoc FullSourceLoc::getSpellingLoc() const { return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); } +FullSourceLoc FullSourceLoc::getFileLoc() const { + assert(isValid()); + return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr); +} + +std::pair<FullSourceLoc, FullSourceLoc> +FullSourceLoc::getImmediateExpansionRange() const { + assert(isValid()); + std::pair<SourceLocation, SourceLocation> Range = + SrcMgr->getImmediateExpansionRange(*this); + return std::make_pair(FullSourceLoc(Range.first, *SrcMgr), + FullSourceLoc(Range.second, *SrcMgr)); +} + +PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const { + if (!isValid()) + return PresumedLoc(); + + return SrcMgr->getPresumedLoc(*this, UseLineDirectives); +} + +bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const { + assert(isValid()); + return SrcMgr->isMacroArgExpansion(*this, StartLoc); +} + +FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const { + assert(isValid()); + return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr); +} + +std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const { + if (!isValid()) + return std::make_pair(FullSourceLoc(), StringRef()); + + std::pair<SourceLocation, StringRef> ImportLoc = + SrcMgr->getModuleImportLoc(*this); + return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr), + ImportLoc.second); +} + +unsigned FullSourceLoc::getFileOffset() const { + assert(isValid()); + return SrcMgr->getFileOffset(*this); +} + +unsigned FullSourceLoc::getLineNumber(bool *Invalid) const { + assert(isValid()); + return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid); +} + +unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const { + assert(isValid()); + return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid); +} + +std::pair<FullSourceLoc, FullSourceLoc> +FullSourceLoc::getExpansionRange() const { + assert(isValid()); + std::pair<SourceLocation, SourceLocation> Range = + SrcMgr->getExpansionRange(*this); + return std::make_pair(FullSourceLoc(Range.first, *SrcMgr), + FullSourceLoc(Range.second, *SrcMgr)); +} + +const FileEntry *FullSourceLoc::getFileEntry() const { + assert(isValid()); + return SrcMgr->getFileEntryForID(getFileID()); +} + unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { assert(isValid()); return SrcMgr->getExpansionLineNumber(*this, Invalid); diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 3936afab21a4..f0b53b4e48a5 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -2018,9 +2018,51 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, if (LOffs.first.isInvalid() || ROffs.first.isInvalid()) return LOffs.first.isInvalid() && !ROffs.first.isInvalid(); + std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs); + if (InSameTU.first) + return InSameTU.second; + + // If we arrived here, the location is either in a built-ins buffer or + // associated with global inline asm. PR5662 and PR22576 are examples. + + StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier(); + StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier(); + bool LIsBuiltins = LB == "<built-in>"; + bool RIsBuiltins = RB == "<built-in>"; + // Sort built-in before non-built-in. + if (LIsBuiltins || RIsBuiltins) { + if (LIsBuiltins != RIsBuiltins) + return LIsBuiltins; + // Both are in built-in buffers, but from different files. We just claim that + // lower IDs come first. + return LOffs.first < ROffs.first; + } + bool LIsAsm = LB == "<inline asm>"; + bool RIsAsm = RB == "<inline asm>"; + // Sort assembler after built-ins, but before the rest. + if (LIsAsm || RIsAsm) { + if (LIsAsm != RIsAsm) + return RIsAsm; + assert(LOffs.first == ROffs.first); + return false; + } + bool LIsScratch = LB == "<scratch space>"; + bool RIsScratch = RB == "<scratch space>"; + // Sort scratch after inline asm, but before the rest. + if (LIsScratch || RIsScratch) { + if (LIsScratch != RIsScratch) + return LIsScratch; + return LOffs.second < ROffs.second; + } + llvm_unreachable("Unsortable locations found"); +} + +std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit( + std::pair<FileID, unsigned> &LOffs, + std::pair<FileID, unsigned> &ROffs) const { // If the source locations are in the same file, just compare offsets. if (LOffs.first == ROffs.first) - return LOffs.second < ROffs.second; + return std::make_pair(true, LOffs.second < ROffs.second); // If we are comparing a source location with multiple locations in the same // file, we get a big win by caching the result. @@ -2030,7 +2072,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, // If we are comparing a source location with multiple locations in the same // file, we get a big win by caching the result. if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first)) - return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); + return std::make_pair( + true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second)); // Okay, we missed in the cache, start updating the cache for this query. IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first, @@ -2060,44 +2103,12 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, // locations within the common file and cache them. if (LOffs.first == ROffs.first) { IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second); - return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); + return std::make_pair( + true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second)); } - - // If we arrived here, the location is either in a built-ins buffer or - // associated with global inline asm. PR5662 and PR22576 are examples. - // Clear the lookup cache, it depends on a common location. IsBeforeInTUCache.clear(); - StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier(); - StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier(); - bool LIsBuiltins = LB == "<built-in>"; - bool RIsBuiltins = RB == "<built-in>"; - // Sort built-in before non-built-in. - if (LIsBuiltins || RIsBuiltins) { - if (LIsBuiltins != RIsBuiltins) - return LIsBuiltins; - // Both are in built-in buffers, but from different files. We just claim that - // lower IDs come first. - return LOffs.first < ROffs.first; - } - bool LIsAsm = LB == "<inline asm>"; - bool RIsAsm = RB == "<inline asm>"; - // Sort assembler after built-ins, but before the rest. - if (LIsAsm || RIsAsm) { - if (LIsAsm != RIsAsm) - return RIsAsm; - assert(LOffs.first == ROffs.first); - return false; - } - bool LIsScratch = LB == "<scratch space>"; - bool RIsScratch = RB == "<scratch space>"; - // Sort scratch after inline asm, but before the rest. - if (LIsScratch || RIsScratch) { - if (LIsScratch != RIsScratch) - return LIsScratch; - return LOffs.second < ROffs.second; - } - llvm_unreachable("Unsortable locations found"); + return std::make_pair(false, false); } void SourceManager::PrintStats() const { diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index c5af99e4b6af..4f04489a4a10 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -2706,7 +2706,7 @@ class X86TargetInfo : public TargetInfo { CK_C3_2, /// This enumerator is a bit odd, as GCC no longer accepts -march=yonah. - /// Clang however has some logic to suport this. + /// Clang however has some logic to support this. // FIXME: Warn, deprecate, and potentially remove this. CK_Yonah, //@} @@ -2737,6 +2737,7 @@ class X86TargetInfo : public TargetInfo { //@{ CK_Bonnell, CK_Silvermont, + CK_Goldmont, //@} /// \name Nehalem @@ -2878,6 +2879,7 @@ class X86TargetInfo : public TargetInfo { .Case("atom", CK_Bonnell) // Legacy name. .Case("silvermont", CK_Silvermont) .Case("slm", CK_Silvermont) // Legacy name. + .Case("goldmont", CK_Goldmont) .Case("nehalem", CK_Nehalem) .Case("corei7", CK_Nehalem) // Legacy name. .Case("westmere", CK_Westmere) @@ -3093,6 +3095,7 @@ public: case CK_Penryn: case CK_Bonnell: case CK_Silvermont: + case CK_Goldmont: case CK_Nehalem: case CK_Westmere: case CK_SandyBridge: @@ -3221,7 +3224,6 @@ bool X86TargetInfo::initFeatureMap( setFeatureEnabledImpl(Features, "cx16", true); break; case CK_Core2: - case CK_Bonnell: setFeatureEnabledImpl(Features, "ssse3", true); setFeatureEnabledImpl(Features, "fxsr", true); setFeatureEnabledImpl(Features, "cx16", true); @@ -3276,7 +3278,6 @@ bool X86TargetInfo::initFeatureMap( setFeatureEnabledImpl(Features, "xsaveopt", true); LLVM_FALLTHROUGH; case CK_Westmere: - case CK_Silvermont: setFeatureEnabledImpl(Features, "aes", true); setFeatureEnabledImpl(Features, "pclmul", true); LLVM_FALLTHROUGH; @@ -3285,6 +3286,28 @@ bool X86TargetInfo::initFeatureMap( setFeatureEnabledImpl(Features, "fxsr", true); setFeatureEnabledImpl(Features, "cx16", true); break; + case CK_Goldmont: + setFeatureEnabledImpl(Features, "sha", true); + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "rdseed", true); + setFeatureEnabledImpl(Features, "xsave", true); + setFeatureEnabledImpl(Features, "xsaveopt", true); + setFeatureEnabledImpl(Features, "xsavec", true); + setFeatureEnabledImpl(Features, "xsaves", true); + setFeatureEnabledImpl(Features, "clflushopt", true); + setFeatureEnabledImpl(Features, "mpx", true); + LLVM_FALLTHROUGH; + case CK_Silvermont: + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "sse4.2", true); + LLVM_FALLTHROUGH; + case CK_Bonnell: + setFeatureEnabledImpl(Features, "movbe", true); + setFeatureEnabledImpl(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "fxsr", true); + setFeatureEnabledImpl(Features, "cx16", true); + break; case CK_KNL: setFeatureEnabledImpl(Features, "avx512f", true); setFeatureEnabledImpl(Features, "avx512cd", true); @@ -3524,6 +3547,7 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features, Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] = Features["avx512vl"] = Features["avx512vbmi"] = Features["avx512ifma"] = Features["avx512vpopcntdq"] = false; + break; } } @@ -3556,6 +3580,7 @@ void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features, LLVM_FALLTHROUGH; case AMD3DNowAthlon: Features["3dnowa"] = false; + break; } } @@ -3590,6 +3615,7 @@ void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level, LLVM_FALLTHROUGH; case XOP: Features["xop"] = false; + break; } } @@ -3893,6 +3919,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_Silvermont: defineCPUMacros(Builder, "slm"); break; + case CK_Goldmont: + defineCPUMacros(Builder, "goldmont"); + break; case CK_Nehalem: case CK_Westmere: case CK_SandyBridge: @@ -4156,6 +4185,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, break; default: Builder.defineMacro("_M_IX86_FP", Twine(0)); + break; } } @@ -5413,7 +5443,7 @@ public: if (Triple.getOS() == llvm::Triple::Linux || Triple.getOS() == llvm::Triple::UnknownOS) this->MCountName = - Opts.EABIVersion == "gnu" ? "\01__gnu_mcount_nc" : "\01mcount"; + Opts.EABIVersion == llvm::EABI::GNU ? "\01__gnu_mcount_nc" : "\01mcount"; } StringRef getABI() const override { return ABI; } @@ -5594,6 +5624,17 @@ public: bool setFPMath(StringRef Name) override; + void getTargetDefinesARMV81A(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); + } + + void getTargetDefinesARMV82A(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Also include the ARMv8.1-A defines + getTargetDefinesARMV81A(Opts, Builder); + } + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { // Target identification. @@ -5792,8 +5833,15 @@ public: if (Opts.UnsafeFPMath) Builder.defineMacro("__ARM_FP_FAST", "1"); - if (ArchKind == llvm::ARM::AK_ARMV8_1A) - Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); + switch(ArchKind) { + default: break; + case llvm::ARM::AK_ARMV8_1A: + getTargetDefinesARMV81A(Opts, Builder); + break; + case llvm::ARM::AK_ARMV8_2A: + getTargetDefinesARMV82A(Opts, Builder); + break; + } } ArrayRef<Builtin::Info> getTargetBuiltins() const override { @@ -6186,9 +6234,8 @@ class AArch64TargetInfo : public TargetInfo { unsigned CRC; unsigned Crypto; unsigned Unaligned; - unsigned V8_1A; - unsigned V8_2A; unsigned HasFullFP16; + llvm::AArch64::ArchKind ArchKind; static const Builtin::Info BuiltinInfo[]; @@ -6236,7 +6283,7 @@ public: if (Triple.getOS() == llvm::Triple::Linux) this->MCountName = "\01_mcount"; else if (Triple.getOS() == llvm::Triple::UnknownOS) - this->MCountName = Opts.EABIVersion == "gnu" ? "\01_mcount" : "mcount"; + this->MCountName = Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount"; } StringRef getABI() const override { return ABI; } @@ -6254,6 +6301,20 @@ public: static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID); } + void getTargetDefinesARMV81A(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); + } + + void getTargetDefinesARMV82A(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Also include the ARMv8.1 defines + getTargetDefinesARMV81A(Opts, Builder); + + if (FPU == NeonMode && HasFullFP16) + Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); + } + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { // Target identification. @@ -6318,10 +6379,15 @@ public: if (Unaligned) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); - if (V8_1A) - Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); - if (V8_2A && FPU == NeonMode && HasFullFP16) - Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); + switch(ArchKind) { + default: break; + case llvm::AArch64::ArchKind::AK_ARMV8_1A: + getTargetDefinesARMV81A(Opts, Builder); + break; + case llvm::AArch64::ArchKind::AK_ARMV8_2A: + getTargetDefinesARMV82A(Opts, Builder); + break; + } // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); @@ -6348,9 +6414,8 @@ public: CRC = 0; Crypto = 0; Unaligned = 1; - V8_1A = 0; - V8_2A = 0; HasFullFP16 = 0; + ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A; for (const auto &Feature : Features) { if (Feature == "+neon") @@ -6362,9 +6427,9 @@ public: if (Feature == "+strict-align") Unaligned = 0; if (Feature == "+v8.1a") - V8_1A = 1; + ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A; if (Feature == "+v8.2a") - V8_2A = 1; + ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A; if (Feature == "+fullfp16") HasFullFP16 = 1; } @@ -6550,6 +6615,43 @@ public: } }; +class MicrosoftARM64TargetInfo + : public WindowsTargetInfo<AArch64leTargetInfo> { + const llvm::Triple Triple; + +public: + MicrosoftARM64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { + WCharType = UnsignedShort; + SizeType = UnsignedLongLong; + TheCXXABI.set(TargetCXXABI::Microsoft); + } + + void setDataLayout() override { + resetDataLayout("e-m:w-i64:64-i128:128-n32:64-S128"); + } + + void getVisualStudioDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, + Builder); + Builder.defineMacro("_WIN32", "1"); + Builder.defineMacro("_WIN64", "1"); + Builder.defineMacro("_M_ARM64", "1"); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsTargetInfo::getTargetDefines(Opts, Builder); + getVisualStudioDefines(Opts, Builder); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } +}; + class AArch64beTargetInfo : public AArch64TargetInfo { void setDataLayout() override { assert(!getTriple().isOSBinFormatMachO()); @@ -7727,6 +7829,148 @@ public: } }; +class Nios2TargetInfo : public TargetInfo { + void setDataLayout() { + if (BigEndian) + resetDataLayout("E-p:32:32:32-i8:8:32-i16:16:32-n32"); + else + resetDataLayout("e-p:32:32:32-i8:8:32-i16:16:32-n32"); + } + + static const Builtin::Info BuiltinInfo[]; + std::string CPU; + std::string ABI; + +public: + Nios2TargetInfo(const llvm::Triple &triple, const TargetOptions &opts) + : TargetInfo(triple), CPU(opts.CPU), ABI(opts.ABI) { + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; + setDataLayout(); + } + + StringRef getABI() const override { return ABI; } + bool setABI(const std::string &Name) override { + if (Name == "o32" || Name == "eabi") { + ABI = Name; + return true; + } + return false; + } + + bool setCPU(const std::string &Name) override { + if (Name == "nios2r1" || Name == "nios2r2") { + CPU = Name; + return true; + } + return false; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + DefineStd(Builder, "nios2", Opts); + DefineStd(Builder, "NIOS2", Opts); + + Builder.defineMacro("__nios2"); + Builder.defineMacro("__NIOS2"); + Builder.defineMacro("__nios2__"); + Builder.defineMacro("__NIOS2__"); + } + + ArrayRef<Builtin::Info> getTargetBuiltins() const override { + return llvm::makeArrayRef(BuiltinInfo, clang::Nios2::LastTSBuiltin - + Builtin::FirstTSBuiltin); + } + + bool isFeatureSupportedByCPU(StringRef Feature, StringRef CPU) const { + const bool isR2 = CPU == "nios2r2"; + return llvm::StringSwitch<bool>(Feature) + .Case("nios2r2mandatory", isR2) + .Case("nios2r2bmx", isR2) + .Case("nios2r2mpx", isR2) + .Case("nios2r2cdx", isR2) + .Default(false); + } + + bool initFeatureMap(llvm::StringMap<bool> &Features, + DiagnosticsEngine &Diags, StringRef CPU, + const std::vector<std::string> &FeatureVec) const override { + static const char *allFeatures[] = { + "nios2r2mandatory", "nios2r2bmx", "nios2r2mpx", "nios2r2cdx" + }; + for (const char *feature : allFeatures) { + Features[feature] = isFeatureSupportedByCPU(feature, CPU); + } + return true; + } + + bool hasFeature(StringRef Feature) const override { + return isFeatureSupportedByCPU(Feature, CPU); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::VoidPtrBuiltinVaList; + } + + ArrayRef<const char *> getGCCRegNames() const override { + static const char *const GCCRegNames[] = { + // CPU register names + // Must match second column of GCCRegAliases + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", + "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", + "r31", + // Floating point register names + "ctl0", "ctl1", "ctl2", "ctl3", "ctl4", "ctl5", "ctl6", "ctl7", "ctl8", + "ctl9", "ctl10", "ctl11", "ctl12", "ctl13", "ctl14", "ctl15" + }; + return llvm::makeArrayRef(GCCRegNames); + } + + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { + switch (*Name) { + default: + return false; + + case 'r': // CPU registers. + case 'd': // Equivalent to "r" unless generating MIPS16 code. + case 'y': // Equivalent to "r", backwards compatibility only. + case 'f': // floating-point registers. + case 'c': // $25 for indirect jumps + case 'l': // lo register + case 'x': // hilo register pair + Info.setAllowsRegister(); + return true; + } + } + + const char *getClobbers() const override { return ""; } + + ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { + static const TargetInfo::GCCRegAlias aliases[] = { + {{"zero"}, "r0"}, {{"at"}, "r1"}, {{"et"}, "r24"}, + {{"bt"}, "r25"}, {{"gp"}, "r26"}, {{"sp"}, "r27"}, + {{"fp"}, "r28"}, {{"ea"}, "r29"}, {{"ba"}, "r30"}, + {{"ra"}, "r31"}, {{"status"}, "ctl0"}, {{"estatus"}, "ctl1"}, + {{"bstatus"}, "ctl2"}, {{"ienable"}, "ctl3"}, {{"ipending"}, "ctl4"}, + {{"cpuid"}, "ctl5"}, {{"exception"}, "ctl7"}, {{"pteaddr"}, "ctl8"}, + {{"tlbacc"}, "ctl9"}, {{"tlbmisc"}, "ctl10"}, {{"badaddr"}, "ctl12"}, + {{"config"}, "ctl13"}, {{"mpubase"}, "ctl14"}, {{"mpuacc"}, "ctl15"}, + }; + return llvm::makeArrayRef(aliases); + } +}; + +const Builtin::Info Nios2TargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, +#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, +#include "clang/Basic/BuiltinsNios2.def" +}; + class MipsTargetInfo : public TargetInfo { void setDataLayout() { StringRef Layout; @@ -9264,6 +9508,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts); case llvm::Triple::OpenBSD: return new OpenBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts); + case llvm::Triple::Win32: + return new MicrosoftARM64TargetInfo(Triple, Opts); default: return new AArch64leTargetInfo(Triple, Opts); } @@ -9353,6 +9599,9 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::msp430: return new MSP430TargetInfo(Triple, Opts); + case llvm::Triple::nios2: + return new LinuxTargetInfo<Nios2TargetInfo>(Triple, Opts); + case llvm::Triple::mips: switch (os) { case llvm::Triple::Linux: diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index bd01902a032b..9b3850abcce7 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -54,6 +54,7 @@ #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Utils/NameAnonGlobals.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" #include <memory> using namespace clang; @@ -414,11 +415,7 @@ static void initTargetOptions(llvm::TargetOptions &Options, Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations; // Set EABI version. - Options.EABIVersion = llvm::StringSwitch<llvm::EABI>(TargetOpts.EABIVersion) - .Case("4", llvm::EABI::EABI4) - .Case("5", llvm::EABI::EABI5) - .Case("gnu", llvm::EABI::GNU) - .Default(llvm::EABI::Default); + Options.EABIVersion = TargetOpts.EABIVersion; if (LangOpts.SjLjExceptions) Options.ExceptionModel = llvm::ExceptionHandling::SjLj; @@ -491,7 +488,6 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize; - PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB; PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP; PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop; @@ -856,11 +852,15 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( if (CodeGenOpts.hasProfileIRUse()) PGOOpt.ProfileUseFile = CodeGenOpts.ProfileInstrumentUsePath; + if (!CodeGenOpts.SampleProfileFile.empty()) + PGOOpt.SampleProfileFile = CodeGenOpts.SampleProfileFile; + // Only pass a PGO options struct if -fprofile-generate or // -fprofile-use were passed on the cmdline. PassBuilder PB(TM.get(), (PGOOpt.RunProfileGen || - !PGOOpt.ProfileUseFile.empty()) ? + !PGOOpt.ProfileUseFile.empty() || + !PGOOpt.SampleProfileFile.empty()) ? Optional<PGOOptions>(PGOOpt) : None); LoopAnalysisManager LAM; @@ -878,20 +878,34 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - ModulePassManager MPM; + ModulePassManager MPM(CodeGenOpts.DebugPassManager); if (!CodeGenOpts.DisableLLVMPasses) { + bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; + bool IsLTO = CodeGenOpts.PrepareForLTO; + if (CodeGenOpts.OptimizationLevel == 0) { // Build a minimal pipeline based on the semantics required by Clang, // which is just that always inlining occurs. MPM.addPass(AlwaysInlinerPass()); + if (IsThinLTO) + MPM.addPass(NameAnonGlobalPass()); } else { - // Otherwise, use the default pass pipeline. We also have to map our - // optimization levels into one of the distinct levels used to configure - // the pipeline. + // Map our optimization levels into one of the distinct levels used to + // configure the pipeline. PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); - MPM = PB.buildPerModuleDefaultPipeline(Level); + if (IsThinLTO) { + MPM = PB.buildThinLTOPreLinkDefaultPipeline( + Level, CodeGenOpts.DebugPassManager); + MPM.addPass(NameAnonGlobalPass()); + } else if (IsLTO) { + MPM = PB.buildLTOPreLinkDefaultPipeline(Level, + CodeGenOpts.DebugPassManager); + } else { + MPM = PB.buildPerModuleDefaultPipeline(Level, + CodeGenOpts.DebugPassManager); + } } } diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a6451b7fc3c1..2a6e92e7f3ce 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9372,6 +9372,16 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_grow_memory, X->getType()); return Builder.CreateCall(Callee, X); } + case WebAssembly::BI__builtin_wasm_throw: { + Value *Tag = EmitScalarExpr(E->getArg(0)); + Value *Obj = EmitScalarExpr(E->getArg(1)); + Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_throw); + return Builder.CreateCall(Callee, {Tag, Obj}); + } + case WebAssembly::BI__builtin_wasm_rethrow: { + Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_rethrow); + return Builder.CreateCall(Callee); + } default: return nullptr; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 38d520a2beb0..13a156c7bbd7 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1297,7 +1297,7 @@ static void CreateCoercedStore(llvm::Value *Src, // If store is legal, just bitcast the src pointer. if (SrcSize <= DstSize) { - Dst = CGF.Builder.CreateBitCast(Dst, llvm::PointerType::getUnqual(SrcTy)); + Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy); BuildAggStore(CGF, Src, Dst, DstIsVolatile); } else { // Otherwise do coercion through memory. This is stupid, but @@ -2412,8 +2412,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Address AddrToStoreInto = Address::invalid(); if (SrcSize <= DstSize) { - AddrToStoreInto = - Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); + AddrToStoreInto = Builder.CreateElementBitCast(Ptr, STy); } else { AddrToStoreInto = CreateTempAlloca(STy, Alloca.getAlignment(), "coerce"); @@ -3389,6 +3388,14 @@ void CodeGenFunction::EmitCallArgs( unsigned Idx = LeftToRight ? I : E - I - 1; CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx; unsigned InitialArgSize = Args.size(); + // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of + // the argument and parameter match or the objc method is parameterized. + assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) || + getContext().hasSameUnqualifiedType((*Arg)->getType(), + ArgTypes[Idx]) || + (isa<ObjCMethodDecl>(AC.getDecl()) && + isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) && + "Argument and parameter types don't match"); EmitCallArg(Args, *Arg, ArgTypes[Idx]); // In particular, we depend on it being the last arg in Args, and the // objectsize bits depend on there only being one arg if !LeftToRight. @@ -3449,7 +3456,6 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, if (const ObjCIndirectCopyRestoreExpr *CRE = dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) { assert(getLangOpts().ObjCAutoRefCount); - assert(getContext().hasSameUnqualifiedType(E->getType(), type)); return emitWritebackArg(*this, args, CRE); } diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index ccd3b8d513b1..4b656ea4a879 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -1860,6 +1860,10 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, lt = Qualifiers::OCL_ExplicitNone; } + // Load objects passed indirectly. + if (Arg.isIndirect() && !ArgVal) + ArgVal = Builder.CreateLoad(DeclPtr); + if (lt == Qualifiers::OCL_Strong) { if (!isConsumed) { if (CGM.getCodeGenOpts().OptimizationLevel == 0) { diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 7976c53d9e98..98435fefbd2e 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1678,7 +1678,10 @@ struct NullReturnState { /// Complete the null-return operation. It is valid to call this /// regardless of whether 'init' has been called. - RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType, + RValue complete(CodeGenFunction &CGF, + ReturnValueSlot returnSlot, + RValue result, + QualType resultType, const CallArgList &CallArgs, const ObjCMethodDecl *Method) { // If we never had to do a null-check, just use the raw result. @@ -1745,7 +1748,8 @@ struct NullReturnState { // memory or (2) agg values in registers. if (result.isAggregate()) { assert(result.isAggregate() && "null init of non-aggregate result?"); - CGF.EmitNullInitialization(result.getAggregateAddress(), resultType); + if (!returnSlot.isUnused()) + CGF.EmitNullInitialization(result.getAggregateAddress(), resultType); if (contBB) CGF.EmitBlock(contBB); return result; } @@ -2117,11 +2121,11 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, } } - NullReturnState nullReturn; + bool RequiresNullCheck = false; llvm::Constant *Fn = nullptr; if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { - if (ReceiverCanBeNull) nullReturn.init(CGF, Arg0); + if (ReceiverCanBeNull) RequiresNullCheck = true; Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) : ObjCTypes.getSendStretFn(IsSuper); } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { @@ -2134,23 +2138,30 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, // arm64 uses objc_msgSend for stret methods and yet null receiver check // must be made for it. if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo)) - nullReturn.init(CGF, Arg0); + RequiresNullCheck = true; Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) : ObjCTypes.getSendFn(IsSuper); } + // We don't need to emit a null check to zero out an indirect result if the + // result is ignored. + if (Return.isUnused()) + RequiresNullCheck = false; + // Emit a null-check if there's a consumed argument other than the receiver. - bool RequiresNullCheck = false; - if (ReceiverCanBeNull && CGM.getLangOpts().ObjCAutoRefCount && Method) { + if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) { for (const auto *ParamDecl : Method->parameters()) { if (ParamDecl->hasAttr<NSConsumedAttr>()) { - if (!nullReturn.NullBB) - nullReturn.init(CGF, Arg0); RequiresNullCheck = true; break; } } } + + NullReturnState nullReturn; + if (RequiresNullCheck) { + nullReturn.init(CGF, Arg0); + } llvm::Instruction *CallSite; Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); @@ -2164,7 +2175,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, llvm::CallSite(CallSite).setDoesNotReturn(); } - return nullReturn.complete(CGF, rvalue, ResultType, CallArgs, + return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs, RequiresNullCheck ? Method : nullptr); } @@ -6381,16 +6392,15 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); if (PTGV) return CGF.Builder.CreateAlignedLoad(PTGV, Align); - PTGV = new llvm::GlobalVariable( - CGM.getModule(), - Init->getType(), false, - llvm::GlobalValue::WeakAnyLinkage, - Init, - ProtocolName); + PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, + llvm::GlobalValue::WeakAnyLinkage, Init, + ProtocolName); PTGV->setSection(GetSectionName("__objc_protorefs", "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); PTGV->setAlignment(Align.getQuantity()); + if (!CGM.getTriple().isOSBinFormatMachO()) + PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName)); CGM.addCompilerUsedGlobal(PTGV); return CGF.Builder.CreateAlignedLoad(PTGV, Align); } @@ -7074,7 +7084,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, CGCallee callee(CGCalleeInfo(), calleePtr); RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args); - return nullReturn.complete(CGF, result, resultType, formalArgs, + return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs, requiresnullCheck ? method : nullptr); } diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index b5599dad3096..4cfddcb107cb 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -26,61 +26,27 @@ using namespace clang; using namespace CodeGen; -static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *OID, - const ObjCImplementationDecl *ID, - const ObjCIvarDecl *Ivar) { - const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); - - // FIXME: We should eliminate the need to have ObjCImplementationDecl passed - // in here; it should never be necessary because that should be the lexical - // decl context for the ivar. - - // If we know have an implementation (and the ivar is in it) then - // look up in the implementation layout. - const ASTRecordLayout *RL; - if (ID && declaresSameEntity(ID->getClassInterface(), Container)) - RL = &CGM.getContext().getASTObjCImplementationLayout(ID); - else - RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); - - // Compute field index. - // - // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is - // implemented. This should be fixed to get the information from the layout - // directly. - unsigned Index = 0; - - for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) { - if (Ivar == IVD) - break; - ++Index; - } - assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); - - return RL->getFieldOffset(Index); -} - uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) { - return LookupFieldBitOffset(CGM, OID, nullptr, Ivar) / - CGM.getContext().getCharWidth(); + return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) / + CGM.getContext().getCharWidth(); } uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, const ObjCImplementationDecl *OID, const ObjCIvarDecl *Ivar) { - return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / - CGM.getContext().getCharWidth(); + return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID, + Ivar) / + CGM.getContext().getCharWidth(); } unsigned CGObjCRuntime::ComputeBitfieldBitOffset( CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *ID, const ObjCIvarDecl *Ivar) { - return LookupFieldBitOffset(CGM, ID, ID->getImplementation(), Ivar); + return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(), + Ivar); } LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, @@ -119,7 +85,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, // Note, there is a subtle invariant here: we can only call this routine on // non-synthesized ivars but we may be called for synthesized ivars. However, // a synthesized ivar can never be a bit-field, so this is safe. - uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, nullptr, Ivar); + uint64_t FieldBitOffset = + CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar); uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 8d83255ac139..3df95a4e9b2a 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -5603,7 +5603,7 @@ public: // We have to process the component lists that relate with the same // declaration in a single chunk so that we can generate the map flags // correctly. Therefore, we organize all lists in a map. - llvm::DenseMap<const ValueDecl *, SmallVector<MapInfo, 8>> Info; + llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; // Helper function to fill the information map for the different supported // clauses. @@ -5927,16 +5927,11 @@ emitOffloadingArrays(CodeGenFunction &CGF, for (unsigned i = 0; i < Info.NumberOfPtrs; ++i) { llvm::Value *BPVal = *BasePointers[i]; - if (BPVal->getType()->isPointerTy()) - BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy); - else { - assert(BPVal->getType()->isIntegerTy() && - "If not a pointer, the value type must be an integer."); - BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy); - } llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), Info.BasePointersArray, 0, i); + BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); CGF.Builder.CreateStore(BPVal, BPAddr); @@ -5945,16 +5940,11 @@ emitOffloadingArrays(CodeGenFunction &CGF, Info.CaptureDeviceAddrMap.insert(std::make_pair(DevVD, BPAddr)); llvm::Value *PVal = Pointers[i]; - if (PVal->getType()->isPointerTy()) - PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy); - else { - assert(PVal->getType()->isIntegerTy() && - "If not a pointer, the value type must be an integer."); - PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy); - } llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), Info.PointersArray, 0, i); + P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); CGF.Builder.CreateStore(PVal, PAddr); diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 77f3c332a12f..493cd627e418 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -239,21 +239,47 @@ static QualType getCanonicalParamType(ASTContext &C, QualType T) { return C.getCanonicalParamType(T); } -llvm::Function * -CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { - assert( - CapturedStmtInfo && - "CapturedStmtInfo should be set when generating the captured function"); - const CapturedDecl *CD = S.getCapturedDecl(); - const RecordDecl *RD = S.getCapturedRecordDecl(); +namespace { + /// Contains required data for proper outlined function codegen. + struct FunctionOptions { + /// Captured statement for which the function is generated. + const CapturedStmt *S = nullptr; + /// true if cast to/from UIntPtr is required for variables captured by + /// value. + bool UIntPtrCastRequired = true; + /// true if only casted argumefnts must be registered as local args or VLA + /// sizes. + bool RegisterCastedArgsOnly = false; + /// Name of the generated function. + StringRef FunctionName; + explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired, + bool RegisterCastedArgsOnly, + StringRef FunctionName) + : S(S), UIntPtrCastRequired(UIntPtrCastRequired), + RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly), + FunctionName(FunctionName) {} + }; +} + +static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue( + CodeGenFunction &CGF, FunctionArgList &Args, + llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>> + &LocalAddrs, + llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> + &VLASizes, + llvm::Value *&CXXThisValue, const FunctionOptions &FO) { + const CapturedDecl *CD = FO.S->getCapturedDecl(); + const RecordDecl *RD = FO.S->getCapturedRecordDecl(); assert(CD->hasBody() && "missing CapturedDecl body"); + CXXThisValue = nullptr; // Build the argument list. + CodeGenModule &CGM = CGF.CGM; ASTContext &Ctx = CGM.getContext(); - FunctionArgList Args; + bool HasUIntPtrArgs = false; Args.append(CD->param_begin(), std::next(CD->param_begin(), CD->getContextParamPosition())); - auto I = S.captures().begin(); + auto I = FO.S->captures().begin(); for (auto *FD : RD->fields()) { QualType ArgType = FD->getType(); IdentifierInfo *II = nullptr; @@ -265,23 +291,24 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { // deal with pointers. We can pass in the same way the VLA type sizes to the // outlined function. if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) || - I->capturesVariableArrayType()) - ArgType = Ctx.getUIntPtrType(); + I->capturesVariableArrayType()) { + HasUIntPtrArgs = true; + if (FO.UIntPtrCastRequired) + ArgType = Ctx.getUIntPtrType(); + } if (I->capturesVariable() || I->capturesVariableByCopy()) { CapVar = I->getCapturedVar(); II = CapVar->getIdentifier(); } else if (I->capturesThis()) - II = &getContext().Idents.get("this"); + II = &Ctx.Idents.get("this"); else { assert(I->capturesVariableArrayType()); - II = &getContext().Idents.get("vla"); + II = &Ctx.Idents.get("vla"); } - if (ArgType->isVariablyModifiedType()) { - ArgType = - getCanonicalParamType(getContext(), ArgType.getNonReferenceType()); - } - Args.push_back(ImplicitParamDecl::Create(getContext(), /*DC=*/nullptr, + if (ArgType->isVariablyModifiedType()) + ArgType = getCanonicalParamType(Ctx, ArgType.getNonReferenceType()); + Args.push_back(ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(), II, ArgType, ImplicitParamDecl::Other)); ++I; @@ -296,90 +323,166 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo); - llvm::Function *F = llvm::Function::Create( - FuncLLVMTy, llvm::GlobalValue::InternalLinkage, - CapturedStmtInfo->getHelperName(), &CGM.getModule()); + llvm::Function *F = + llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage, + FO.FunctionName, &CGM.getModule()); CGM.SetInternalFunctionAttributes(CD, F, FuncInfo); if (CD->isNothrow()) F->addFnAttr(llvm::Attribute::NoUnwind); // Generate the function. - StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(), - CD->getBody()->getLocStart()); + CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(), + CD->getBody()->getLocStart()); unsigned Cnt = CD->getContextParamPosition(); - I = S.captures().begin(); + I = FO.S->captures().begin(); for (auto *FD : RD->fields()) { // If we are capturing a pointer by copy we don't need to do anything, just // use the value that we get from the arguments. if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) { const VarDecl *CurVD = I->getCapturedVar(); - Address LocalAddr = GetAddrOfLocalVar(Args[Cnt]); + Address LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]); // If the variable is a reference we need to materialize it here. if (CurVD->getType()->isReferenceType()) { - Address RefAddr = CreateMemTemp(CurVD->getType(), getPointerAlign(), - ".materialized_ref"); - EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, /*Volatile=*/false, - CurVD->getType()); + Address RefAddr = CGF.CreateMemTemp( + CurVD->getType(), CGM.getPointerAlign(), ".materialized_ref"); + CGF.EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, + /*Volatile=*/false, CurVD->getType()); LocalAddr = RefAddr; } - setAddrOfLocalVar(CurVD, LocalAddr); + if (!FO.RegisterCastedArgsOnly) + LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}}); ++Cnt; ++I; continue; } LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - LValue ArgLVal = - MakeAddrLValue(GetAddrOfLocalVar(Args[Cnt]), Args[Cnt]->getType(), - BaseInfo); + LValue ArgLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(Args[Cnt]), + Args[Cnt]->getType(), BaseInfo); if (FD->hasCapturedVLAType()) { - LValue CastedArgLVal = - MakeAddrLValue(castValueFromUintptr(*this, FD->getType(), - Args[Cnt]->getName(), ArgLVal), - FD->getType(), BaseInfo); + if (FO.UIntPtrCastRequired) { + ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(), + Args[Cnt]->getName(), + ArgLVal), + FD->getType(), BaseInfo); + } auto *ExprArg = - EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal(); + CGF.EmitLoadOfLValue(ArgLVal, SourceLocation()).getScalarVal(); auto VAT = FD->getCapturedVLAType(); - VLASizeMap[VAT->getSizeExpr()] = ExprArg; + VLASizes.insert({Args[Cnt], {VAT->getSizeExpr(), ExprArg}}); } else if (I->capturesVariable()) { auto *Var = I->getCapturedVar(); QualType VarTy = Var->getType(); Address ArgAddr = ArgLVal.getAddress(); if (!VarTy->isReferenceType()) { if (ArgLVal.getType()->isLValueReferenceType()) { - ArgAddr = EmitLoadOfReference( + ArgAddr = CGF.EmitLoadOfReference( ArgAddr, ArgLVal.getType()->castAs<ReferenceType>()); } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) { assert(ArgLVal.getType()->isPointerType()); - ArgAddr = EmitLoadOfPointer( + ArgAddr = CGF.EmitLoadOfPointer( ArgAddr, ArgLVal.getType()->castAs<PointerType>()); } } - setAddrOfLocalVar( - Var, Address(ArgAddr.getPointer(), getContext().getDeclAlign(Var))); + if (!FO.RegisterCastedArgsOnly) { + LocalAddrs.insert( + {Args[Cnt], + {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}}); + } } else if (I->capturesVariableByCopy()) { assert(!FD->getType()->isAnyPointerType() && "Not expecting a captured pointer."); auto *Var = I->getCapturedVar(); QualType VarTy = Var->getType(); - setAddrOfLocalVar(Var, castValueFromUintptr(*this, FD->getType(), - Args[Cnt]->getName(), ArgLVal, - VarTy->isReferenceType())); + LocalAddrs.insert( + {Args[Cnt], + {Var, + FO.UIntPtrCastRequired + ? castValueFromUintptr(CGF, FD->getType(), Args[Cnt]->getName(), + ArgLVal, VarTy->isReferenceType()) + : ArgLVal.getAddress()}}); } else { // If 'this' is captured, load it into CXXThisValue. assert(I->capturesThis()); - CXXThisValue = - EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation()).getScalarVal(); + CXXThisValue = CGF.EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation()) + .getScalarVal(); + LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}}); } ++Cnt; ++I; } + return {F, HasUIntPtrArgs}; +} + +llvm::Function * +CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { + assert( + CapturedStmtInfo && + "CapturedStmtInfo should be set when generating the captured function"); + const CapturedDecl *CD = S.getCapturedDecl(); + // Build the argument list. + bool NeedWrapperFunction = + getDebugInfo() && + CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo; + FunctionArgList Args; + llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs; + llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes; + FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false, + CapturedStmtInfo->getHelperName()); + llvm::Function *F; + bool HasUIntPtrArgs; + std::tie(F, HasUIntPtrArgs) = emitOutlinedFunctionPrologue( + *this, Args, LocalAddrs, VLASizes, CXXThisValue, FO); + for (const auto &LocalAddrPair : LocalAddrs) { + if (LocalAddrPair.second.first) { + setAddrOfLocalVar(LocalAddrPair.second.first, + LocalAddrPair.second.second); + } + } + for (const auto &VLASizePair : VLASizes) + VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second; PGO.assignRegionCounters(GlobalDecl(CD), F); CapturedStmtInfo->EmitBody(*this, CD->getBody()); FinishFunction(CD->getBodyRBrace()); - - return F; + if (!NeedWrapperFunction || !HasUIntPtrArgs) + return F; + + FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true, + /*RegisterCastedArgsOnly=*/true, + ".nondebug_wrapper."); + CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true); + WrapperCGF.disableDebugInfo(); + Args.clear(); + LocalAddrs.clear(); + VLASizes.clear(); + llvm::Function *WrapperF = + emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes, + WrapperCGF.CXXThisValue, WrapperFO).first; + LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); + llvm::SmallVector<llvm::Value *, 4> CallArgs; + for (const auto *Arg : Args) { + llvm::Value *CallArg; + auto I = LocalAddrs.find(Arg); + if (I != LocalAddrs.end()) { + LValue LV = + WrapperCGF.MakeAddrLValue(I->second.second, Arg->getType(), BaseInfo); + CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation()); + } else { + auto EI = VLASizes.find(Arg); + if (EI != VLASizes.end()) + CallArg = EI->second.second; + else { + LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg), + Arg->getType(), BaseInfo); + CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation()); + } + } + CallArgs.emplace_back(CallArg); + } + WrapperCGF.Builder.CreateCall(F, CallArgs); + WrapperCGF.FinishFunction(); + return WrapperF; } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp index c7e30fad7575..4f03de55149b 100644 --- a/lib/CodeGen/CodeGenAction.cpp +++ b/lib/CodeGen/CodeGenAction.cpp @@ -228,7 +228,10 @@ namespace clang { Ctx.getDiagnosticHandler(); void *OldDiagnosticContext = Ctx.getDiagnosticContext(); Ctx.setDiagnosticHandler(DiagnosticHandler, this); - Ctx.setDiagnosticHotnessRequested(CodeGenOpts.DiagnosticsWithHotness); + Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness); + if (CodeGenOpts.DiagnosticsHotnessThreshold != 0) + Ctx.setDiagnosticsHotnessThreshold( + CodeGenOpts.DiagnosticsHotnessThreshold); std::unique_ptr<llvm::tool_output_file> OptRecordFile; if (!CodeGenOpts.OptRecordFile.empty()) { @@ -246,7 +249,7 @@ namespace clang { llvm::make_unique<yaml::Output>(OptRecordFile->os())); if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) - Ctx.setDiagnosticHotnessRequested(true); + Ctx.setDiagnosticsHotnessRequested(true); } // Link each LinkModule into our module. diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index 9e193531d0f6..c3d66c1dabc5 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -617,6 +617,9 @@ uint64_t PGOHash::finalize() { void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { const Decl *D = GD.getDecl(); + if (!D->hasBody()) + return; + bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr(); llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); if (!InstrumentRegions && !PGOReader) diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index 5c13e59a0d73..cf86644fb8cd 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -23,10 +23,11 @@ using namespace clang; using namespace llvm::opt; Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain, - InputArgList *_Args, DerivedArgList *_TranslatedArgs) + InputArgList *_Args, DerivedArgList *_TranslatedArgs, + bool ContainsError) : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u), Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr), - ForDiagnostics(false) { + ForDiagnostics(false), ContainsError(ContainsError) { // The offloading host toolchain is the default tool chain. OrderedOffloadingToolchains.insert( std::make_pair(Action::OFK_Host, &DefaultToolChain)); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index f23975829eaf..faced0697ed9 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -153,8 +153,10 @@ void Driver::setDriverModeFromOption(StringRef Opt) { Diag(diag::err_drv_unsupported_option_argument) << OptName << Value; } -InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) { +InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings, + bool &ContainsError) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); + ContainsError = false; unsigned IncludedFlagsBitmask; unsigned ExcludedFlagsBitmask; @@ -167,27 +169,41 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) { IncludedFlagsBitmask, ExcludedFlagsBitmask); // Check for missing argument error. - if (MissingArgCount) - Diag(clang::diag::err_drv_missing_argument) + if (MissingArgCount) { + Diag(diag::err_drv_missing_argument) << Args.getArgString(MissingArgIndex) << MissingArgCount; + ContainsError |= + Diags.getDiagnosticLevel(diag::err_drv_missing_argument, + SourceLocation()) > DiagnosticsEngine::Warning; + } // Check for unsupported options. for (const Arg *A : Args) { if (A->getOption().hasFlag(options::Unsupported)) { - Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(Args); + Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args); + ContainsError |= Diags.getDiagnosticLevel(diag::err_drv_unsupported_opt, + SourceLocation()) > + DiagnosticsEngine::Warning; continue; } // Warn about -mcpu= without an argument. if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) { - Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(Args); + Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args); + ContainsError |= Diags.getDiagnosticLevel( + diag::warn_drv_empty_joined_argument, + SourceLocation()) > DiagnosticsEngine::Warning; } } - for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) - Diags.Report(IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl : - diag::err_drv_unknown_argument) - << A->getAsString(Args); + for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) { + auto ID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl + : diag::err_drv_unknown_argument; + + Diags.Report(ID) << A->getAsString(Args); + ContainsError |= Diags.getDiagnosticLevel(ID, SourceLocation()) > + DiagnosticsEngine::Warning; + } return Args; } @@ -600,9 +616,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintPhases; - InputArgList Args = ParseArgStrings(ArgList.slice(1)); - if (Diags.hasErrorOccurred()) - return nullptr; + bool ContainsError; + InputArgList Args = ParseArgStrings(ArgList.slice(1), ContainsError); // Silence driver warnings if requested Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w)); @@ -692,7 +707,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { *UArgs, computeTargetTriple(*this, DefaultTargetTriple, *UArgs)); // The compilation takes ownership of Args. - Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs); + Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs, + ContainsError); if (!HandleImmediateArgs(*C)) return C; diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 3a30f2a289b0..7a442c83e158 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -32,7 +32,7 @@ enum : SanitizerMask { RequiresPIE = DataFlow, NeedsUnwindTables = Address | Thread | Memory | DataFlow, SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined | - Integer | Nullability | DataFlow, + Integer | Nullability | DataFlow | Fuzzer, RecoverableByDefault = Undefined | Integer | Nullability, Unrecoverable = Unreachable | Return, LegacyFsanitizeRecoverMask = Undefined | Integer, diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp index 4eac97620114..8cafd3c74bfb 100644 --- a/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/lib/Driver/ToolChains/Arch/ARM.cpp @@ -392,9 +392,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC, if (B->getOption().matches(options::OPT_mlong_calls)) D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); } - - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-execute-only"); + Features.push_back("+execute-only"); } } } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 292cf72b56ca..3731aa83ef06 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -35,6 +35,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" +#include "llvm/Support/TargetParser.h" #include "llvm/Support/YAMLParser.h" #ifdef LLVM_ON_UNIX @@ -129,6 +130,13 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA, else if (JA.isDeviceOffloading(Action::OFK_Cuda)) Work(*C.getSingleOffloadToolChain<Action::OFK_Host>()); + if (JA.isHostOffloading(Action::OFK_OpenMP)) { + auto TCs = C.getOffloadToolChains<Action::OFK_OpenMP>(); + for (auto II = TCs.first, IE = TCs.second; II != IE; ++II) + Work(*II->second); + } else if (JA.isDeviceOffloading(Action::OFK_OpenMP)) + Work(*C.getSingleOffloadToolChain<Action::OFK_Host>()); + // // TODO: Add support for other offloading programming models here. // @@ -781,15 +789,14 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, CmdArgs.push_back("-femit-coverage-data"); if (Args.hasFlag(options::OPT_fcoverage_mapping, - options::OPT_fno_coverage_mapping, false) && - !ProfileGenerateArg) - D.Diag(clang::diag::err_drv_argument_only_allowed_with) - << "-fcoverage-mapping" - << "-fprofile-instr-generate"; + options::OPT_fno_coverage_mapping, false)) { + if (!ProfileGenerateArg) + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << "-fcoverage-mapping" + << "-fprofile-instr-generate"; - if (Args.hasFlag(options::OPT_fcoverage_mapping, - options::OPT_fno_coverage_mapping, false)) CmdArgs.push_back("-fcoverage-mapping"); + } if (C.getArgs().hasArg(options::OPT_c) || C.getArgs().hasArg(options::OPT_S)) { @@ -1309,43 +1316,13 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, // FIXME: Support -meabi. // FIXME: Parts of this are duplicated in the backend, unify this somehow. const char *ABIName = nullptr; - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(); - } else if (Triple.isOSBinFormatMachO()) { - if (arm::useAAPCSForMachO(Triple)) { - ABIName = "aapcs"; - } else if (Triple.isWatchABI()) { - ABIName = "aapcs16"; - } else { - ABIName = "apcs-gnu"; - } - } else if (Triple.isOSWindows()) { - // FIXME: this is invalid for WindowsCE - ABIName = "aapcs"; - } else { - // Select the default based on the platform. - switch (Triple.getEnvironment()) { - case llvm::Triple::Android: - case llvm::Triple::GNUEABI: - case llvm::Triple::GNUEABIHF: - case llvm::Triple::MuslEABI: - case llvm::Triple::MuslEABIHF: - ABIName = "aapcs-linux"; - break; - case llvm::Triple::EABIHF: - case llvm::Triple::EABI: - ABIName = "aapcs"; - break; - default: - if (Triple.getOS() == llvm::Triple::NetBSD) - ABIName = "apcs-gnu"; - else if (Triple.getOS() == llvm::Triple::OpenBSD) - ABIName = "aapcs-linux"; - else - ABIName = "aapcs"; - break; - } + else { + std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false); + ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data(); } + CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); @@ -1993,6 +1970,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(NormalizedTriple)); } + if (IsOpenMPDevice) { + // We have to pass the triple of the host if compiling for an OpenMP device. + std::string NormalizedTriple = + C.getSingleOffloadToolChain<Action::OFK_Host>() + ->getTriple() + .normalize(); + CmdArgs.push_back("-aux-triple"); + CmdArgs.push_back(Args.MakeArgString(NormalizedTriple)); + } + if (Triple.isOSWindows() && (Triple.getArch() == llvm::Triple::arm || Triple.getArch() == llvm::Triple::thumb)) { unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6; @@ -4056,6 +4043,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_diagnostics_show_hotness, false)) CmdArgs.push_back("-fdiagnostics-show-hotness"); + if (const Arg *A = + Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) { + std::string Opt = std::string("-fdiagnostics-hotness-threshold=") + A->getValue(); + CmdArgs.push_back(Args.MakeArgString(Opt)); + } + if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) { CmdArgs.push_back("-fdiagnostics-format"); CmdArgs.push_back(A->getValue()); @@ -4140,11 +4133,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_slp_vectorize, EnableSLPVec)) CmdArgs.push_back("-vectorize-slp"); - // -fno-slp-vectorize-aggressive is default. - if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive, - options::OPT_fno_slp_vectorize_aggressive, false)) - CmdArgs.push_back("-vectorize-slp-aggressive"); - if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) A->render(Args, CmdArgs); @@ -4413,10 +4401,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // device declarations can be identified. Also, -fopenmp-is-device is passed // along to tell the frontend that it is generating code for a device, so that // only the relevant declarations are emitted. - if (IsOpenMPDevice && Inputs.size() == 2) { + if (IsOpenMPDevice) { CmdArgs.push_back("-fopenmp-is-device"); - CmdArgs.push_back("-fopenmp-host-ir-file-path"); - CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename())); + if (Inputs.size() == 2) { + CmdArgs.push_back("-fopenmp-host-ir-file-path"); + CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename())); + } } // For all the host OpenMP offloading compile jobs we need to pass the targets diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 5e360f62e21a..e8bb703054de 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -215,6 +215,21 @@ static std::string getR600TargetGPU(const ArgList &Args) { return ""; } +static std::string getNios2TargetCPU(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_mcpu_EQ); + if (!A) + A = Args.getLastArg(options::OPT_march_EQ); + + if (!A) + return ""; + + const char *name = A->getValue(); + return llvm::StringSwitch<const char *>(name) + .Case("r1", "nios2r1") + .Case("r2", "nios2r2") + .Default(name); +} + static std::string getLanaiTargetCPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { return A->getValue(); @@ -267,6 +282,10 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, return A->getValue(); return ""; + case llvm::Triple::nios2: { + return getNios2TargetCPU(Args); + } + case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -598,7 +617,8 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols); // Inject libfuzzer dependencies. - if (TC.getSanitizerArgs().needsFuzzer()) { + if (TC.getSanitizerArgs().needsFuzzer() + && !Args.hasArg(options::OPT_shared)) { addLibFuzzerRuntime(TC, Args, CmdArgs); } diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp index d290c62a056a..7d0c438b1360 100644 --- a/lib/Driver/ToolChains/CrossWindows.cpp +++ b/lib/Driver/ToolChains/CrossWindows.cpp @@ -238,8 +238,15 @@ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, const Driver &D = getDriver(); const std::string &SysRoot = D.SysRoot; - if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + auto AddSystemAfterIncludes = [&]() { + for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after)) + addSystemInclude(DriverArgs, CC1Args, P); + }; + + if (DriverArgs.hasArg(options::OPT_nostdinc)) { + AddSystemAfterIncludes(); return; + } addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { @@ -247,8 +254,7 @@ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::sys::path::append(ResourceDir, "include"); addSystemInclude(DriverArgs, CC1Args, ResourceDir); } - for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after)) - addSystemInclude(DriverArgs, CC1Args, P); + AddSystemAfterIncludes(); addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); } @@ -258,7 +264,7 @@ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, const llvm::Triple &Triple = getTriple(); const std::string &SysRoot = getDriver().SysRoot; - if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + if (DriverArgs.hasArg(options::OPT_nostdinc) || DriverArgs.hasArg(options::OPT_nostdincxx)) return; diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index e41b50c40b28..7b61095c3ba9 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -1053,7 +1053,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); - if (Sanitize.needsFuzzer()) + if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) AddFuzzerLinkArgs(Args, CmdArgs); if (Sanitize.needsStatsRt()) { StringRef OS = isTargetMacOS() ? "osx" : "iossim"; @@ -1150,6 +1150,17 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Args.getLastArg(options::OPT_mwatchos_version_min_EQ, options::OPT_mwatchos_simulator_version_min_EQ); + unsigned Major, Minor, Micro; + bool HadExtra; + + // iOS 10 is the maximum deployment target for 32-bit targets. + if (iOSVersion && getTriple().isArch32Bit() && + Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro, + HadExtra) && + Major > 10) + getDriver().Diag(diag::err_invalid_ios_deployment_target) + << iOSVersion->getAsString(Args); + // Add a macro to differentiate between m(iphone|tv|watch)os-version-min=X.Y and // -m(iphone|tv|watch)simulator-version-min=X.Y. if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ) || @@ -1191,6 +1202,14 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (char *env = ::getenv("WATCHOS_DEPLOYMENT_TARGET")) WatchOSTarget = env; + // iOS 10 is the maximum deployment target for 32-bit targets. + if (!iOSTarget.empty() && getTriple().isArch32Bit() && + Driver::GetReleaseVersion(iOSTarget.c_str(), Major, Minor, Micro, + HadExtra) && + Major > 10) + getDriver().Diag(diag::err_invalid_ios_deployment_target) + << std::string("IPHONEOS_DEPLOYMENT_TARGET=") + iOSTarget; + // If there is no command-line argument to specify the Target version and // no environment variable defined, see if we can set the default based // on -isysroot. @@ -1308,8 +1327,6 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { llvm_unreachable("Unable to infer Darwin variant"); // Set the tool chain target information. - unsigned Major, Minor, Micro; - bool HadExtra; if (Platform == MacOS) { assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) && "Unknown target platform!"); @@ -1325,6 +1342,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << iOSVersion->getAsString(Args); + // iOS 10 is the maximum deployment target for 32-bit targets. If the + // inferred deployment target is iOS 11 or later, set it to 10.99. + if (getTriple().isArch32Bit() && Major >= 11) { + Major = 10; + Minor = 99; + Micro = 99; + } } else if (Platform == TvOS) { if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || @@ -1667,6 +1691,28 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args, AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true); } +bool Darwin::isAlignedAllocationUnavailable() const { + switch (TargetPlatform) { + case MacOS: // Earlier than 10.13. + return TargetVersion < VersionTuple(10U, 13U, 0U); + case IPhoneOS: + case IPhoneOSSimulator: + case TvOS: + case TvOSSimulator: // Earlier than 11.0. + return TargetVersion < VersionTuple(11U, 0U, 0U); + case WatchOS: + case WatchOSSimulator: // Earlier than 4.0. + return TargetVersion < VersionTuple(4U, 0U, 0U); + } + llvm_unreachable("Unsupported platform"); +} + +void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + if (isAlignedAllocationUnavailable()) + CC1Args.push_back("-faligned-alloc-unavailable"); +} + DerivedArgList * Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const { diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h index 16ed04286ac0..ffcdf9a71a46 100644 --- a/lib/Driver/ToolChains/Darwin.h +++ b/lib/Driver/ToolChains/Darwin.h @@ -384,6 +384,14 @@ protected: return TargetVersion < VersionTuple(V0, V1, V2); } + /// Return true if c++17 aligned allocation/deallocation functions are not + /// implemented in the c++ standard library of the deployment target we are + /// targeting. + bool isAlignedAllocationUnavailable() const; + + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + StringRef getPlatformFamily() const; static StringRef getSDKName(StringRef isysroot); StringRef getOSLibraryNameSuffix() const; diff --git a/lib/Driver/ToolChains/MipsLinux.cpp b/lib/Driver/ToolChains/MipsLinux.cpp index 709c396a64b7..b394208336ed 100644 --- a/lib/Driver/ToolChains/MipsLinux.cpp +++ b/lib/Driver/ToolChains/MipsLinux.cpp @@ -109,7 +109,7 @@ std::string MipsLLVMToolChain::findLibCxxIncludePath() const { void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) && - "Only -lc++ (aka libxx) is suported in this toolchain."); + "Only -lc++ (aka libxx) is supported in this toolchain."); CmdArgs.push_back("-lc++"); CmdArgs.push_back("-lc++abi"); diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index cca773cfe3cb..4197587a74c0 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -56,6 +56,8 @@ static bool startsNextParameter(const FormatToken &Current, if (Current.is(TT_CtorInitializerComma) && Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) return true; + if (Style.Language == FormatStyle::LK_Proto && Current.is(TT_SelectorName)) + return true; return Previous.is(tok::comma) && !Current.isTrailingComment() && ((Previous.isNot(TT_CtorInitializerComma) || Style.BreakConstructorInitializers != @@ -499,6 +501,13 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, } } +static bool lessOpensProtoMessageField(const FormatToken &LessTok, + const LineState &State) { + assert(LessTok.is(tok::less)); + return LessTok.NestingLevel > 0 || + (LessTok.Previous && LessTok.Previous->is(tok::equal)); +} + unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, bool DryRun) { FormatToken &Current = *State.NextToken; @@ -641,6 +650,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, // before the corresponding } or ]. if (PreviousNonComment && (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_Proto && + PreviousNonComment->is(tok::less) && + lessOpensProtoMessageField(*PreviousNonComment, State)) || (PreviousNonComment->is(TT_TemplateString) && PreviousNonComment->opensScope()))) State.Stack.back().BreakBeforeClosingBrace = true; @@ -682,7 +694,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block) return Current.NestingLevel == 0 ? State.FirstIndent : State.Stack.back().Indent; - if (Current.isOneOf(tok::r_brace, tok::r_square) && State.Stack.size() > 1) { + if ((Current.isOneOf(tok::r_brace, tok::r_square) || + (Current.is(tok::greater) && Style.Language == FormatStyle::LK_Proto)) && + State.Stack.size() > 1) { if (Current.closesBlockOrBlockTypeList(Style)) return State.Stack[State.Stack.size() - 2].NestedBlockIndent; if (Current.MatchingParen && @@ -1035,7 +1049,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, bool BreakBeforeParameter = false; unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall, State.Stack.back().NestedBlockIndent); - if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) { + if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || + (Style.Language == FormatStyle::LK_Proto && Current.is(tok::less) && + lessOpensProtoMessageField(Current, State))) { if (Current.opensBlockOrBlockTypeList(Style)) { NewIndent = Style.IndentWidth + std::min(State.Column, State.Stack.back().NestedBlockIndent); @@ -1047,12 +1063,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, Current.MatchingParen->Previous && Current.MatchingParen->Previous->is(tok::comma); AvoidBinPacking = - (Current.is(TT_ArrayInitializerLSquare) && EndsInComma) || - Current.is(TT_DictLiteral) || + EndsInComma || Current.is(TT_DictLiteral) || Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments || (NextNoComment && NextNoComment->isOneOf(TT_DesignatedInitializerPeriod, TT_DesignatedInitializerLSquare)); + BreakBeforeParameter = EndsInComma; if (Current.ParameterCount > 1) NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1); } else { diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 7659d56adf25..bb6781d79517 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -44,7 +44,6 @@ using clang::format::FormatStyle; -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string) LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory) namespace llvm { @@ -414,7 +413,9 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); IO.mapOptional("BeforeElse", Wrapping.BeforeElse); IO.mapOptional("IndentBraces", Wrapping.IndentBraces); - IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody); + IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); + IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord); + IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace); } }; @@ -490,7 +491,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) { return Style; FormatStyle Expanded = Style; Expanded.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false, true}; + false, false, false, false, false, true, + true, true}; switch (Style.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; @@ -503,7 +505,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; - Expanded.BraceWrapping.SplitEmptyFunctionBody = false; + Expanded.BraceWrapping.SplitEmptyFunction = false; + Expanded.BraceWrapping.SplitEmptyRecord = false; break; case FormatStyle::BS_Stroustrup: Expanded.BraceWrapping.AfterFunction = true; @@ -523,7 +526,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) { break; case FormatStyle::BS_GNU: Expanded.BraceWrapping = {true, true, true, true, true, true, - true, true, true, true, true, true}; + true, true, true, true, true, true, + true, true}; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -560,7 +564,8 @@ FormatStyle getLLVMStyle() { LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; LLVMStyle.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false, true}; + false, false, false, false, false, true, + true, true}; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakBeforeInheritanceComma = false; @@ -579,9 +584,9 @@ FormatStyle getLLVMStyle() { LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2}, - {"^(<|\"(gtest|isl|json)/)", 3}, + {"^(<|\"(gtest|gmock|isl|json)/)", 3}, {".*", 1}}; - LLVMStyle.IncludeIsMainRegex = "$"; + LLVMStyle.IncludeIsMainRegex = "(Test)?$"; LLVMStyle.IndentCaseLabels = false; LLVMStyle.IndentWrappedFunctionNames = false; LLVMStyle.IndentWidth = 2; @@ -1409,7 +1414,7 @@ public: : Style(Style), FileName(FileName) { FileStem = llvm::sys::path::stem(FileName); for (const auto &Category : Style.IncludeCategories) - CategoryRegexs.emplace_back(Category.Regex); + CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase); IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") || FileName.endswith(".cpp") || FileName.endswith(".c++") || FileName.endswith(".cxx") || FileName.endswith(".m") || @@ -1437,9 +1442,11 @@ private: return false; StringRef HeaderStem = llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1)); - if (FileStem.startswith(HeaderStem)) { + if (FileStem.startswith(HeaderStem) || + FileStem.startswith_lower(HeaderStem)) { llvm::Regex MainIncludeRegex( - (HeaderStem + Style.IncludeIsMainRegex).str()); + (HeaderStem + Style.IncludeIsMainRegex).str(), + llvm::Regex::IgnoreCase); if (MainIncludeRegex.match(FileStem)) return true; } diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index c5bf48cdcc06..0fe91adcd472 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -465,7 +465,8 @@ struct FormatToken { return is(TT_ArrayInitializerLSquare) || (is(tok::l_brace) && (BlockKind == BK_Block || is(TT_DictLiteral) || - (!Style.Cpp11BracedListStyle && NestingLevel == 0))); + (!Style.Cpp11BracedListStyle && NestingLevel == 0))) || + (is(tok::less) && Style.Language == FormatStyle::LK_Proto); } /// \brief Same as opensBlockOrBlockTypeList, but for the closing token. @@ -475,6 +476,19 @@ struct FormatToken { return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style); } + /// \brief Return the actual namespace token, if this token starts a namespace + /// block. + const FormatToken *getNamespaceToken() const { + const FormatToken *NamespaceTok = this; + if (is(tok::comment)) + NamespaceTok = NamespaceTok->getNextNonComment(); + // Detect "(inline)? namespace" in the beginning of a line. + if (NamespaceTok && NamespaceTok->is(tok::kw_inline)) + NamespaceTok = NamespaceTok->getNextNonComment(); + return NamespaceTok && NamespaceTok->is(tok::kw_namespace) ? NamespaceTok + : nullptr; + } + private: // Disallow copying. FormatToken(const FormatToken &) = delete; diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp index 1bbb41f757ae..85b70b8c0a76 100644 --- a/lib/Format/NamespaceEndCommentsFixer.cpp +++ b/lib/Format/NamespaceEndCommentsFixer.cpp @@ -174,7 +174,7 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( AllNamespaceNames = "::" + NamespaceName + AllNamespaceNames; continue; } - NamespaceName += std::move(AllNamespaceNames); + NamespaceName += AllNamespaceNames; CompactedNamespacesCount = 0; AllNamespaceNames = std::string(); } diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 505f42ec9a06..d78a37532fe8 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -89,7 +89,8 @@ private: continue; } if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) || - (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext)) + (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext && + Style.Language != FormatStyle::LK_Proto)) return false; // If a && or || is found and interpreted as a binary operator, this set // of angles is likely part of something like "a < b && c > d". If the @@ -103,6 +104,14 @@ private: !Line.startsWith(tok::kw_template)) return false; updateParameterCount(Left, CurrentToken); + if (Style.Language == FormatStyle::LK_Proto) { + if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) { + if (CurrentToken->is(tok::colon) || + (CurrentToken->isOneOf(tok::l_brace, tok::less) && + Previous->isNot(tok::colon))) + Previous->Type = TT_SelectorName; + } + } if (!consumeToken()) return false; } @@ -440,7 +449,7 @@ private: if (CurrentToken->isOneOf(tok::r_paren, tok::r_square)) return false; updateParameterCount(Left, CurrentToken); - if (CurrentToken->isOneOf(tok::colon, tok::l_brace)) { + if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) { FormatToken *Previous = CurrentToken->getPreviousNonComment(); if (((CurrentToken->is(tok::colon) && (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) || @@ -1561,8 +1570,10 @@ private: const FormatToken *NextNonComment = Current->getNextNonComment(); if (Current->is(TT_ConditionalExpr)) return prec::Conditional; - if (NextNonComment && NextNonComment->is(tok::colon) && - NextNonComment->is(TT_DictLiteral)) + if (NextNonComment && Current->is(TT_SelectorName) && + (NextNonComment->is(TT_DictLiteral) || + (Style.Language == FormatStyle::LK_Proto && + NextNonComment->is(tok::less)))) return prec::Assignment; if (Current->is(TT_JsComputedPropertyName)) return prec::Assignment; @@ -2549,10 +2560,16 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // deliberate choice and might have aligned the contents of the string // literal accordingly. Thus, we try keep existing line breaks. return Right.NewlinesBefore > 0; - if (Right.Previous->is(tok::l_brace) && Right.NestingLevel == 1 && - Style.Language == FormatStyle::LK_Proto) - // Don't put enums onto single lines in protocol buffers. + if ((Right.Previous->is(tok::l_brace) || + (Right.Previous->is(tok::less) && + Right.Previous->Previous && + Right.Previous->Previous->is(tok::equal)) + ) && + Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) { + // Don't put enums or option definitions onto single lines in protocol + // buffers. return true; + } if (Right.is(TT_InlineASMBrace)) return Right.HasUnescapedNewline; if (isAllmanBrace(Left) || isAllmanBrace(Right)) diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index 8836c07cac71..2005a2822924 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -136,10 +136,7 @@ private: bool isNamespaceDeclaration(const AnnotatedLine *Line) { const FormatToken *NamespaceTok = Line->First; - // Detect "(inline)? namespace" in the beginning of a line. - if (NamespaceTok->is(tok::kw_inline)) - NamespaceTok = NamespaceTok->getNextNonComment(); - return NamespaceTok && NamespaceTok->is(tok::kw_namespace); + return NamespaceTok && NamespaceTok->getNamespaceToken(); } bool isEndOfNamespace(const AnnotatedLine *Line, @@ -216,10 +213,31 @@ private: if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First == TheLine->Last && - !Style.BraceWrapping.SplitEmptyFunctionBody && + !Style.BraceWrapping.SplitEmptyFunction && I[1]->First->is(tok::r_brace)) return tryMergeSimpleBlock(I, E, Limit); + // Handle empty record blocks where the brace has already been wrapped + if (TheLine->Last->is(tok::l_brace) && TheLine->First == TheLine->Last && + I != AnnotatedLines.begin()) { + bool EmptyBlock = I[1]->First->is(tok::r_brace); + + const FormatToken *Tok = I[-1]->First; + if (Tok && Tok->is(tok::comment)) + Tok = Tok->getNextNonComment(); + + if (Tok && Tok->getNamespaceToken()) + return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock + ? tryMergeSimpleBlock(I, E, Limit) : 0; + + if (Tok && Tok->is(tok::kw_typedef)) + Tok = Tok->getNextNonComment(); + if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union, + Keywords.kw_interface)) + return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock + ? tryMergeSimpleBlock(I, E, Limit) : 0; + } + // FIXME: TheLine->Level != 0 might or might not be the right check to do. // If necessary, change to something smarter. bool MergeShortFunctions = diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index f7678bb6b2a5..ba3a4c17ee12 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -1176,9 +1176,12 @@ void UnwrappedLineParser::parseStructuralElement() { } nextToken(); - if (FormatTok->Tok.is(tok::l_brace)) { + if (FormatTok->Tok.is(tok::l_brace)) parseBracedList(); - } + else if (Style.Language == FormatStyle::LK_Proto && + FormatTok->Tok.is(tok::less)) + parseBracedList(/*ContinueOnSemicolons=*/false, + /*ClosingBraceKind=*/tok::greater); break; case tok::l_square: parseSquare(); @@ -1346,7 +1349,8 @@ bool UnwrappedLineParser::tryToParseBracedList() { return true; } -bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { +bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons, + tok::TokenKind ClosingBraceKind) { bool HasError = false; nextToken(); @@ -1375,6 +1379,10 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { parseChildBlock(); } } + if (FormatTok->Tok.getKind() == ClosingBraceKind) { + nextToken(); + return !HasError; + } switch (FormatTok->Tok.getKind()) { case tok::caret: nextToken(); @@ -1401,9 +1409,6 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { FormatTok->BlockKind = BK_BracedInit; parseBracedList(); break; - case tok::r_brace: - nextToken(); - return !HasError; case tok::semi: // JavaScript (or more precisely TypeScript) can have semicolons in braced // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index 15d1d9cda7a2..a2aa2f006728 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -93,7 +93,8 @@ private: void readTokenWithJavaScriptASI(); void parseStructuralElement(); bool tryToParseBracedList(); - bool parseBracedList(bool ContinueOnSemicolons = false); + bool parseBracedList(bool ContinueOnSemicolons = false, + tok::TokenKind ClosingBraceKind = tok::r_brace); void parseParens(); void parseSquare(); void parseIfThenElse(); diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index 986f98ae598b..354527db7bad 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -44,9 +44,9 @@ void ASTMergeAction::ExecuteAction() { new ForwardingDiagnosticConsumer( *CI.getDiagnostics().getClient()), /*ShouldOwnClient=*/true)); - std::unique_ptr<ASTUnit> Unit = - ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerReader(), - Diags, CI.getFileSystemOpts(), false); + std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile( + ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags, + CI.getFileSystemOpts(), false); if (!Unit) continue; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 1f34f10f55af..1094e6d089a6 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -458,7 +458,7 @@ namespace { /// a Preprocessor. class ASTInfoCollector : public ASTReaderListener { Preprocessor &PP; - ASTContext &Context; + ASTContext *Context; HeaderSearchOptions &HSOpts; PreprocessorOptions &PPOpts; LangOptions &LangOpt; @@ -468,7 +468,7 @@ class ASTInfoCollector : public ASTReaderListener { bool InitializedLanguage; public: - ASTInfoCollector(Preprocessor &PP, ASTContext &Context, + ASTInfoCollector(Preprocessor &PP, ASTContext *Context, HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, LangOptions &LangOpt, std::shared_ptr<TargetOptions> &TargetOpts, @@ -536,12 +536,15 @@ private: // Initialize the preprocessor. PP.Initialize(*Target); + if (!Context) + return; + // Initialize the ASTContext - Context.InitBuiltinTypes(*Target); + Context->InitBuiltinTypes(*Target); // We didn't have access to the comment options when the ASTContext was // constructed, so register them now. - Context.getCommentCommandTraits().registerCommentOptions( + Context->getCommentCommandTraits().registerCommentOptions( LangOpt.CommentOpts); } }; @@ -671,7 +674,7 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( const std::string &Filename, const PCHContainerReader &PCHContainerRdr, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool UseDebugInfo, bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles, bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors, @@ -722,21 +725,21 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( /*OwnsHeaderSearch=*/false); Preprocessor &PP = *AST->PP; - AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), - PP.getIdentifierTable(), PP.getSelectorTable(), - PP.getBuiltinInfo()); - ASTContext &Context = *AST->Ctx; + if (ToLoad >= LoadASTOnly) + AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), + PP.getIdentifierTable(), PP.getSelectorTable(), + PP.getBuiltinInfo()); bool disableValid = false; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = true; - AST->Reader = new ASTReader(PP, Context, PCHContainerRdr, { }, + AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, { }, /*isysroot=*/"", /*DisableValidation=*/disableValid, AllowPCHWithCompilerErrors); AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>( - *AST->PP, Context, *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, + *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, AST->TargetOpts, AST->Target, Counter)); // Attach the AST reader to the AST context as an external AST @@ -744,7 +747,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( // AST file as needed. // We need the external source to be set up before we read the AST, because // eagerly-deserialized declarations may use it. - Context.setExternalSource(AST->Reader); + if (AST->Ctx) + AST->Ctx->setExternalSource(AST->Reader); switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile, SourceLocation(), ASTReader::ARR_None)) { @@ -766,15 +770,18 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( PP.setCounterValue(Counter); // Create an AST consumer, even though it isn't used. - AST->Consumer.reset(new ASTConsumer); - + if (ToLoad >= LoadASTOnly) + AST->Consumer.reset(new ASTConsumer); + // Create a semantic analysis object and tell the AST reader about it. - AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer)); - AST->TheSema->Initialize(); - AST->Reader->InitializeSema(*AST->TheSema); + if (ToLoad >= LoadEverything) { + AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer)); + AST->TheSema->Initialize(); + AST->Reader->InitializeSema(*AST->TheSema); + } // Tell the diagnostic client that we have started a source file. - AST->getDiagnostics().getClient()->BeginSourceFile(Context.getLangOpts(),&PP); + AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP); return AST; } @@ -1638,7 +1645,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( &StoredDiagnostics, nullptr); CI = clang::createInvocationFromCommandLine( - llvm::makeArrayRef(ArgBegin, ArgEnd), Diags); + llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS); if (!CI) return nullptr; } diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp index b984c2ed0dd5..534c7587f48d 100644 --- a/lib/Frontend/ChainedIncludesSource.cpp +++ b/lib/Frontend/ChainedIncludesSource.cpp @@ -83,7 +83,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, ASTDeserializationListener *deserialListener = nullptr) { Preprocessor &PP = CI.getPreprocessor(); std::unique_ptr<ASTReader> Reader; - Reader.reset(new ASTReader(PP, CI.getASTContext(), + Reader.reset(new ASTReader(PP, &CI.getASTContext(), CI.getPCHContainerReader(), /*Extensions=*/{ }, /*isysroot=*/"", /*DisableValidation=*/true)); diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index e5da2ae4f22e..bb6a665cb456 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -517,7 +517,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader( - PP, Context, PCHContainerRdr, Extensions, + PP, &Context, PCHContainerRdr, Extensions, Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation, AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex)); @@ -825,8 +825,11 @@ bool CompilerInstance::InitializeSourceManager( const FrontendInputFile &Input, DiagnosticsEngine &Diags, FileManager &FileMgr, SourceManager &SourceMgr, HeaderSearch *HS, DependencyOutputOptions &DepOpts, const FrontendOptions &Opts) { - SrcMgr::CharacteristicKind - Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User; + SrcMgr::CharacteristicKind Kind = + Input.getKind().getFormat() == InputKind::ModuleMap + ? Input.isSystem() ? SrcMgr::C_System_ModuleMap + : SrcMgr::C_User_ModuleMap + : Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User; if (Input.isBuffer()) { SourceMgr.setMainFileID(SourceMgr.createFileID( @@ -933,8 +936,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { if (!hasTarget()) return false; - // Create TargetInfo for the other side of CUDA compilation. - if (getLangOpts().CUDA && !getFrontendOpts().AuxTriple.empty()) { + // Create TargetInfo for the other side of CUDA and OpenMP compilation. + if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) && + !getFrontendOpts().AuxTriple.empty()) { auto TO = std::make_shared<TargetOptions>(); TO->Triple = getFrontendOpts().AuxTriple; TO->HostTriple = getTarget().getTriple().str(); @@ -1469,7 +1473,7 @@ void CompilerInstance::createModuleManager() { "Reading modules", *FrontendTimerGroup); ModuleManager = new ASTReader( - getPreprocessor(), getASTContext(), getPCHContainerReader(), + getPreprocessor(), &getASTContext(), getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, /*AllowASTWithCompilerErrors=*/false, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 6254b0013bab..00f6b9b46f03 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -476,6 +476,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, /* Default */ false); + Opts.DebugPassManager = + Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager, + /* Default */ false); + if (Arg *A = Args.getLastArg(OPT_fveclib)) { StringRef Name = A->getValue(); if (Name == "Accelerate") @@ -668,7 +672,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.MSVolatile = Args.hasArg(OPT_fms_volatile); - Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive); Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); @@ -906,12 +909,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DiagnosticsWithHotness = Args.hasArg(options::OPT_fdiagnostics_show_hotness); bool UsingSampleProfile = !Opts.SampleProfileFile.empty(); + bool UsingProfile = UsingSampleProfile || + (Opts.getProfileUse() != CodeGenOptions::ProfileNone); - if (Opts.DiagnosticsWithHotness && - Opts.getProfileUse() == CodeGenOptions::ProfileNone && - !UsingSampleProfile) { - Diags.Report(diag::warn_drv_fdiagnostics_show_hotness_requires_pgo); - } + if (Opts.DiagnosticsWithHotness && !UsingProfile) + Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) + << "-fdiagnostics-show-hotness"; + + Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value( + Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0); + if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile) + Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) + << "-fdiagnostics-hotness-threshold="; // If the user requested to use a sample profile for PGO, then the // backend will need to track source location information so the profile @@ -2106,6 +2115,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.AlignedAllocation = Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation, Opts.AlignedAllocation); + Opts.AlignedAllocationUnavailable = + Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable); Opts.NewAlignOverride = getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags); if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) { @@ -2557,7 +2568,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value; else - Opts.EABIVersion = Value; + Opts.EABIVersion = EABIVersion; } Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.FPMath = Args.getLastArgValue(OPT_mfpmath); @@ -2644,6 +2655,10 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; } + // Set the triple of the host for OpenMP device compile. + if (LangOpts.OpenMPIsDevice) + Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; + // FIXME: Override value name discarding when asan or msan is used because the // backend passes depend on the name of the alloca in order to print out // names. diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp index 49d459e78c45..c3ce7ce2b742 100644 --- a/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -31,8 +31,8 @@ using namespace llvm::opt; /// \return A CompilerInvocation, or 0 if none was built for the given /// argument vector. std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine( - ArrayRef<const char *> ArgList, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags) { + ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + IntrusiveRefCntPtr<vfs::FileSystem> VFS) { if (!Diags.get()) { // No diagnostics engine was provided, so create our own diagnostics object // with the default options. @@ -46,7 +46,7 @@ std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine( // FIXME: We shouldn't have to pass in the path info. driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(), - *Diags); + *Diags, VFS); // Don't check that inputs exist, they may have been remapped. TheDriver.setCheckInputsExist(false); diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index bd14c53e4d15..561eb9c4a316 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -55,8 +55,8 @@ struct DepCollectorPPCallbacks : public PPCallbacks { llvm::sys::path::remove_leading_dotslash(FE->getName()); DepCollector.maybeAddDependency(Filename, /*FromModule*/false, - FileType != SrcMgr::C_User, - /*IsModuleFile*/false, /*IsMissing*/false); + isSystem(FileType), + /*IsModuleFile*/false, /*IsMissing*/false); } void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, @@ -265,7 +265,7 @@ bool DFGImpl::FileMatchesDepCriteria(const char *Filename, if (IncludeSystemHeaders) return true; - return FileType == SrcMgr::C_User; + return !isSystem(FileType); } void DFGImpl::FileChanged(SourceLocation Loc, diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index 177feac97441..e3263843e29b 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -76,20 +76,19 @@ static void mergeFixits(ArrayRef<FixItHint> FixItHints, } } -void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, +void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, - const SourceManager *SM, DiagOrStoredDiag D) { - assert(SM || Loc.isInvalid()); + assert(Loc.hasManager() || Loc.isInvalid()); beginDiagnostic(D, Level); if (!Loc.isValid()) // If we have no source location, just emit the diagnostic message. - emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); + emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, D); else { // Get the ranges into a local array we can hack on. SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), @@ -97,7 +96,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, SmallVector<FixItHint, 8> MergedFixits; if (!FixItHints.empty()) { - mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); + mergeFixits(FixItHints, Loc.getManager(), LangOpts, MergedFixits); FixItHints = MergedFixits; } @@ -107,25 +106,25 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, if (I->RemoveRange.isValid()) MutableRanges.push_back(I->RemoveRange); - SourceLocation UnexpandedLoc = Loc; + FullSourceLoc UnexpandedLoc = Loc; // Find the ultimate expansion location for the diagnostic. - Loc = SM->getFileLoc(Loc); + Loc = Loc.getFileLoc(); - PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); + PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc); // First, if this diagnostic is not in the main file, print out the // "included from" lines. - emitIncludeStack(Loc, PLoc, Level, *SM); + emitIncludeStack(Loc, PLoc, Level); // Next, emit the actual diagnostic message and caret. - emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); - emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); + emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D); + emitCaret(Loc, Level, MutableRanges, FixItHints); // If this location is within a macro, walk from UnexpandedLoc up to Loc // and produce a macro backtrace. if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { - emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM); + emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints); } } @@ -139,15 +138,12 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), Diag.getRanges(), Diag.getFixIts(), - Diag.getLocation().isValid() ? &Diag.getLocation().getManager() - : nullptr, &Diag); } void DiagnosticRenderer::emitBasicNote(StringRef Message) { - emitDiagnosticMessage( - SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message, - None, nullptr, DiagOrStoredDiag()); + emitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagnosticsEngine::Note, + Message, None, DiagOrStoredDiag()); } /// \brief Prints an include stack when appropriate for a particular @@ -161,12 +157,11 @@ void DiagnosticRenderer::emitBasicNote(StringRef Message) { /// \param Loc The diagnostic location. /// \param PLoc The presumed location of the diagnostic location. /// \param Level The diagnostic level of the message this stack pertains to. -void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - const SourceManager &SM) { - SourceLocation IncludeLoc = - PLoc.isInvalid() ? SourceLocation() : PLoc.getIncludeLoc(); +void DiagnosticRenderer::emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level) { + FullSourceLoc IncludeLoc = + PLoc.isInvalid() ? FullSourceLoc() + : FullSourceLoc(PLoc.getIncludeLoc(), Loc.getManager()); // Skip redundant include stacks altogether. if (LastIncludeLoc == IncludeLoc) @@ -178,74 +173,70 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, return; if (IncludeLoc.isValid()) - emitIncludeStackRecursively(IncludeLoc, SM); + emitIncludeStackRecursively(IncludeLoc); else { - emitModuleBuildStack(SM); - emitImportStack(Loc, SM); + emitModuleBuildStack(Loc.getManager()); + emitImportStack(Loc); } } /// \brief Helper to recursivly walk up the include stack and print each layer /// on the way back down. -void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, - const SourceManager &SM) { +void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) { if (Loc.isInvalid()) { - emitModuleBuildStack(SM); + emitModuleBuildStack(Loc.getManager()); return; } - - PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); + + PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc); if (PLoc.isInvalid()) return; // If this source location was imported from a module, print the module // import stack rather than the // FIXME: We want submodule granularity here. - std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); + std::pair<FullSourceLoc, StringRef> Imported = Loc.getModuleImportLoc(); if (!Imported.second.empty()) { // This location was imported by a module. Emit the module import stack. - emitImportStackRecursively(Imported.first, Imported.second, SM); + emitImportStackRecursively(Imported.first, Imported.second); return; } // Emit the other include frames first. - emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); - + emitIncludeStackRecursively( + FullSourceLoc(PLoc.getIncludeLoc(), Loc.getManager())); + // Emit the inclusion text/note. - emitIncludeLocation(Loc, PLoc, SM); + emitIncludeLocation(Loc, PLoc); } /// \brief Emit the module import stack associated with the current location. -void DiagnosticRenderer::emitImportStack(SourceLocation Loc, - const SourceManager &SM) { +void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) { if (Loc.isInvalid()) { - emitModuleBuildStack(SM); + emitModuleBuildStack(Loc.getManager()); return; } - std::pair<SourceLocation, StringRef> NextImportLoc - = SM.getModuleImportLoc(Loc); - emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); + std::pair<FullSourceLoc, StringRef> NextImportLoc = Loc.getModuleImportLoc(); + emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second); } /// \brief Helper to recursivly walk up the import stack and print each layer /// on the way back down. -void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, - StringRef ModuleName, - const SourceManager &SM) { +void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc, + StringRef ModuleName) { if (ModuleName.empty()) { return; } - PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); + PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc); // Emit the other import frames first. - std::pair<SourceLocation, StringRef> NextImportLoc - = SM.getModuleImportLoc(Loc); - emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); + std::pair<FullSourceLoc, StringRef> NextImportLoc = Loc.getModuleImportLoc(); + emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second); // Emit the inclusion text/note. - emitImportLocation(Loc, PLoc, ModuleName, SM); + emitImportLocation(Loc, PLoc, ModuleName); } /// \brief Emit the module build stack, for cases where a module is (re-)built @@ -253,13 +244,9 @@ void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { ModuleBuildStack Stack = SM.getModuleBuildStack(); for (unsigned I = 0, N = Stack.size(); I != N; ++I) { - const SourceManager &CurSM = Stack[I].second.getManager(); - SourceLocation CurLoc = Stack[I].second; - emitBuildingModuleLocation(CurLoc, - CurSM.getPresumedLoc(CurLoc, + emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc( DiagOpts->ShowPresumedLoc), - Stack[I].first, - CurSM); + Stack[I].first); } } @@ -348,12 +335,12 @@ static void computeCommonMacroArgExpansionFileIDs( // in the same expansion as the caret; otherwise, we crawl to the top of // each chain. Two locations are part of the same macro expansion // iff the FileID is the same. -static void mapDiagnosticRanges( - SourceLocation CaretLoc, - ArrayRef<CharSourceRange> Ranges, - SmallVectorImpl<CharSourceRange> &SpellingRanges, - const SourceManager *SM) { - FileID CaretLocFileID = SM->getFileID(CaretLoc); +static void +mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges, + SmallVectorImpl<CharSourceRange> &SpellingRanges) { + FileID CaretLocFileID = CaretLoc.getFileID(); + + const SourceManager *SM = &CaretLoc.getManager(); for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (I->isInvalid()) continue; @@ -404,42 +391,39 @@ static void mapDiagnosticRanges( } } -void DiagnosticRenderer::emitCaret(SourceLocation Loc, +void DiagnosticRenderer::emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) { + ArrayRef<FixItHint> Hints) { SmallVector<CharSourceRange, 4> SpellingRanges; - mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); - emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); + mapDiagnosticRanges(Loc, Ranges, SpellingRanges); + emitCodeContext(Loc, Level, SpellingRanges, Hints); } /// \brief A helper function for emitMacroExpansion to print the /// macro expansion message void DiagnosticRenderer::emitSingleMacroExpansion( - SourceLocation Loc, - DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) { + FullSourceLoc Loc, DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges) { // Find the spelling location for the macro definition. We must use the // spelling location here to avoid emitting a macro backtrace for the note. - SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); + FullSourceLoc SpellingLoc = Loc.getSpellingLoc(); // Map the ranges into the FileID of the diagnostic location. SmallVector<CharSourceRange, 4> SpellingRanges; - mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); + mapDiagnosticRanges(Loc, Ranges, SpellingRanges); SmallString<100> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); - StringRef MacroName = - Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts); + StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics( + Loc, Loc.getManager(), LangOpts); if (MacroName.empty()) Message << "expanded from here"; else Message << "expanded from macro '" << MacroName << "'"; emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), - SpellingRanges, None, &SM); + SpellingRanges, None); } /// Check that the macro argument location of Loc starts with ArgumentLoc. @@ -473,13 +457,12 @@ static bool checkRangeForMacroArgExpansion(CharSourceRange Range, /// A helper function to check if the current ranges are all inside the same /// macro argument expansion as Loc. -static bool checkRangesForMacroArgExpansion(SourceLocation Loc, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) { +static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc, + ArrayRef<CharSourceRange> Ranges) { assert(Loc.isMacroID() && "Must be a macro expansion!"); SmallVector<CharSourceRange, 4> SpellingRanges; - mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); + mapDiagnosticRanges(Loc, Ranges, SpellingRanges); /// Count all valid ranges. unsigned ValidCount = 0; @@ -490,15 +473,15 @@ static bool checkRangesForMacroArgExpansion(SourceLocation Loc, return false; /// To store the source location of the argument location. - SourceLocation ArgumentLoc; + FullSourceLoc ArgumentLoc; /// Set the ArgumentLoc to the beginning location of the expansion of Loc /// so to check if the ranges expands to the same beginning location. - if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc)) + if (!Loc.isMacroArgExpansion(&ArgumentLoc)) return false; for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { - if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc)) + if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc)) return false; } @@ -516,34 +499,33 @@ static bool checkRangesForMacroArgExpansion(SourceLocation Loc, /// \param Level The diagnostic level currently being emitted. /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. -void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, +void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) { + ArrayRef<FixItHint> Hints) { assert(Loc.isValid() && "must have a valid source location here"); // Produce a stack of macro backtraces. - SmallVector<SourceLocation, 8> LocationStack; + SmallVector<FullSourceLoc, 8> LocationStack; unsigned IgnoredEnd = 0; while (Loc.isMacroID()) { // If this is the expansion of a macro argument, point the caret at the // use of the argument in the definition of the macro, not the expansion. - if (SM.isMacroArgExpansion(Loc)) - LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first); + if (Loc.isMacroArgExpansion()) + LocationStack.push_back(Loc.getImmediateExpansionRange().first); else LocationStack.push_back(Loc); - if (checkRangesForMacroArgExpansion(Loc, Ranges, SM)) + if (checkRangesForMacroArgExpansion(Loc, Ranges)) IgnoredEnd = LocationStack.size(); - Loc = SM.getImmediateMacroCallerLoc(Loc); + Loc = Loc.getImmediateMacroCallerLoc(); // Once the location no longer points into a macro, try stepping through // the last found location. This sometimes produces additional useful // backtraces. if (Loc.isFileID()) - Loc = SM.getImmediateMacroCallerLoc(LocationStack.back()); + Loc = LocationStack.back().getImmediateMacroCallerLoc(); assert(Loc.isValid() && "must have a valid source location here"); } @@ -555,7 +537,7 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, if (MacroDepth <= MacroLimit || MacroLimit == 0) { for (auto I = LocationStack.rbegin(), E = LocationStack.rend(); I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges, SM); + emitSingleMacroExpansion(*I, Level, Ranges); return; } @@ -565,7 +547,7 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, for (auto I = LocationStack.rbegin(), E = LocationStack.rbegin() + MacroStartMessages; I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges, SM); + emitSingleMacroExpansion(*I, Level, Ranges); SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -577,26 +559,24 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, for (auto I = LocationStack.rend() - MacroEndMessages, E = LocationStack.rend(); I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges, SM); + emitSingleMacroExpansion(*I, Level, Ranges); } DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} -void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc, - const SourceManager &SM) { +void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc, + PresumedLoc PLoc) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); Message << "in file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; - emitNote(Loc, Message.str(), &SM); + emitNote(Loc, Message.str()); } -void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, +void DiagnosticNoteRenderer::emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { + StringRef ModuleName) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -605,14 +585,12 @@ void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, Message << "' imported from " << PLoc.getFilename() << ':' << PLoc.getLine(); Message << ":"; - emitNote(Loc, Message.str(), &SM); + emitNote(Loc, Message.str()); } -void -DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, - PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { +void DiagnosticNoteRenderer::emitBuildingModuleLocation(FullSourceLoc Loc, + PresumedLoc PLoc, + StringRef ModuleName) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -621,5 +599,5 @@ DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; else Message << "while building module '" << ModuleName << "':"; - emitNote(Loc, Message.str(), &SM); + emitNote(Loc, Message.str()); } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index f81a06b31869..704d51509851 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -200,12 +200,12 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, /// /// \param CI The compiler instance. /// \param InputFile Populated with the filename from the line marker. -/// \param AddLineNote If \c true, add a line note corresponding to this line -/// directive. Only use this if the directive will not actually be -/// visited by the preprocessor. +/// \param IsModuleMap If \c true, add a line note corresponding to this line +/// directive. (We need to do this because the directive will not be +/// visited by the preprocessor.) static SourceLocation ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile, - bool AddLineNote = false) { + bool IsModuleMap = false) { auto &SourceMgr = CI.getSourceManager(); auto MainFileID = SourceMgr.getMainFileID(); @@ -231,7 +231,7 @@ static SourceLocation ReadOriginalFileName(CompilerInstance &CI, unsigned LineNo; SourceLocation LineNoLoc = T.getLocation(); - if (AddLineNote) { + if (IsModuleMap) { llvm::SmallString<16> Buffer; if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts()) .getAsInteger(10, LineNo)) @@ -250,10 +250,10 @@ static SourceLocation ReadOriginalFileName(CompilerInstance &CI, return SourceLocation(); InputFile = Literal.GetString().str(); - if (AddLineNote) + if (IsModuleMap) CI.getSourceManager().AddLineNote( LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false, - false, SrcMgr::C_User); + false, SrcMgr::C_User_ModuleMap); return T.getLocation(); } @@ -403,7 +403,7 @@ static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem, Offset = 0; if (IsPreprocessed) { SourceLocation EndOfLineMarker = - ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true); + ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true); if (EndOfLineMarker.isValid()) Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second; } @@ -536,8 +536,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false); std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( - InputFile, CI.getPCHContainerReader(), ASTDiags, CI.getFileSystemOpts(), - CI.getCodeGenOpts().DebugTypeExtRefs); + InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly, + ASTDiags, CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs); if (!AST) goto failure; @@ -547,27 +547,36 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, CI.getPreprocessorOpts() = AST->getPreprocessorOpts(); CI.getLangOpts() = AST->getLangOpts(); - // Preload all the module files loaded transitively by the AST unit. - if (auto ASTReader = AST->getASTReader()) { - auto &MM = ASTReader->getModuleManager(); - for (ModuleFile &MF : MM) - if (&MF != &MM.getPrimaryModule()) - CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName); - } - // FIXME: Preload module maps loaded by the AST unit. - // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.createSourceManager(CI.getFileManager()); CI.getSourceManager().initializeForReplay(AST->getSourceManager()); + // Preload all the module files loaded transitively by the AST unit. Also + // load all module map files that were parsed as part of building the AST + // unit. + if (auto ASTReader = AST->getASTReader()) { + auto &MM = ASTReader->getModuleManager(); + auto &PrimaryModule = MM.getPrimaryModule(); + + for (ModuleFile &MF : MM) + if (&MF != &PrimaryModule) + CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName); + + ASTReader->visitTopLevelModuleMaps(PrimaryModule, + [&](const FileEntry *FE) { + CI.getFrontendOpts().ModuleMapFiles.push_back(FE->getName()); + }); + } + // Set up the input file for replay purposes. auto Kind = AST->getInputKind(); if (Kind.getFormat() == InputKind::ModuleMap) { Module *ASTModule = AST->getPreprocessor().getHeaderSearchInfo().lookupModule( AST->getLangOpts().CurrentModule, /*AllowSearch*/ false); + assert(ASTModule && "module file does not define its own module"); Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind); } else { auto &SM = CI.getSourceManager(); @@ -590,8 +599,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( - InputFile, CI.getPCHContainerReader(), Diags, CI.getFileSystemOpts(), - CI.getCodeGenOpts().DebugTypeExtRefs); + InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags, + CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs); if (!AST) goto failure; diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 9621889b27ad..0fbcc1c7399e 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -230,7 +230,7 @@ void VerifyPCHAction::ExecuteAction() { bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; std::unique_ptr<ASTReader> Reader(new ASTReader( - CI.getPreprocessor(), CI.getASTContext(), CI.getPCHContainerReader(), + CI.getPreprocessor(), &CI.getASTContext(), CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), /*DisableValidation*/ false, diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 08befb33c962..71420df00025 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -1043,7 +1043,7 @@ void clang::InitializePreprocessor( if (InitOpts.UsePredefines) { // FIXME: This will create multiple definitions for most of the predefined // macros. This is not the right way to handle this. - if (LangOpts.CUDA && PP.getAuxTargetInfo()) + if ((LangOpts.CUDA || LangOpts.OpenMPIsDevice) && PP.getAuxTargetInfo()) InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts, Builder); diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp index 9b34d4211353..ede12aab6e69 100644 --- a/lib/Frontend/ModuleDependencyCollector.cpp +++ b/lib/Frontend/ModuleDependencyCollector.cpp @@ -248,7 +248,7 @@ std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src, // Always map a canonical src path to its real path into the YAML, by doing // this we map different virtual src paths to the same entry in the VFS // overlay, which is a way to emulate symlink inside the VFS; this is also - // needed for correctness, not doing that can lead to module redifinition + // needed for correctness, not doing that can lead to module redefinition // errors. addFileMapping(VirtualPath, CacheDst); return std::error_code(); diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp index b5a5acd8ad9a..7666fe10b381 100644 --- a/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -63,27 +63,20 @@ public: ~SDiagsRenderer() override {} protected: - void emitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, + void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, - const SourceManager *SM, DiagOrStoredDiag D) override; - void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) override {} + ArrayRef<CharSourceRange> Ranges) override {} - void emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) override; + void emitNote(FullSourceLoc Loc, StringRef Message) override; - void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) override; + void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints) override; void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) override; @@ -193,11 +186,8 @@ private: void ExitDiagBlock(); /// \brief Emit a DIAG record. - void EmitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, - const SourceManager *SM, + void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, DiagOrStoredDiag D); /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic. @@ -220,16 +210,14 @@ private: /// \brief Emit (lazily) the file string and retrieved the file identifier. unsigned getEmitFile(const char *Filename); - /// \brief Add SourceLocation information the specified record. - void AddLocToRecord(SourceLocation Loc, const SourceManager *SM, - PresumedLoc PLoc, RecordDataImpl &Record, - unsigned TokSize = 0); + /// \brief Add SourceLocation information the specified record. + void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, + RecordDataImpl &Record, unsigned TokSize = 0); /// \brief Add SourceLocation information the specified record. - void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, - const SourceManager *SM, + void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record, unsigned TokSize = 0) { - AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(), + AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(), Record, TokSize); } @@ -350,11 +338,8 @@ static void EmitRecordID(unsigned ID, const char *Name, Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); } -void SDiagsWriter::AddLocToRecord(SourceLocation Loc, - const SourceManager *SM, - PresumedLoc PLoc, - RecordDataImpl &Record, - unsigned TokSize) { +void SDiagsWriter::AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, + RecordDataImpl &Record, unsigned TokSize) { if (PLoc.isInvalid()) { // Emit a "sentinel" location. Record.push_back((unsigned)0); // File. @@ -367,19 +352,19 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc, Record.push_back(getEmitFile(PLoc.getFilename())); Record.push_back(PLoc.getLine()); Record.push_back(PLoc.getColumn()+TokSize); - Record.push_back(SM->getFileOffset(Loc)); + Record.push_back(Loc.getFileOffset()); } void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, RecordDataImpl &Record, const SourceManager &SM) { - AddLocToRecord(Range.getBegin(), Record, &SM); + AddLocToRecord(FullSourceLoc(Range.getBegin(), SM), Record); unsigned TokSize = 0; if (Range.isTokenRange()) TokSize = Lexer::MeasureTokenLength(Range.getEnd(), SM, *LangOpts); - - AddLocToRecord(Range.getEnd(), Record, &SM, TokSize); + + AddLocToRecord(FullSourceLoc(Range.getEnd(), SM), Record, TokSize); } unsigned SDiagsWriter::getEmitFile(const char *FileName){ @@ -606,8 +591,8 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, if (DiagLevel == DiagnosticsEngine::Note) EnterDiagBlock(); - EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel, - State->diagBuf, nullptr, &Info); + EmitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagLevel, + State->diagBuf, &Info); if (DiagLevel == DiagnosticsEngine::Note) ExitDiagBlock(); @@ -618,12 +603,9 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, assert(Info.hasSourceManager() && LangOpts && "Unexpected diagnostic with valid location outside of a source file"); SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts); - Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, - State->diagBuf, - Info.getRanges(), - Info.getFixItHints(), - &Info.getSourceManager(), - &Info); + Renderer.emitDiagnostic( + FullSourceLoc(Info.getLocation(), Info.getSourceManager()), DiagLevel, + State->diagBuf, Info.getRanges(), Info.getFixItHints(), &Info); } static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) { @@ -641,11 +623,9 @@ static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) { llvm_unreachable("invalid diagnostic level"); } -void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, +void SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, - const SourceManager *SM, DiagOrStoredDiag D) { llvm::BitstreamWriter &Stream = State->Stream; RecordData &Record = State->Record; @@ -655,7 +635,7 @@ void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc, Record.clear(); Record.push_back(RECORD_DIAG); Record.push_back(getStableLevel(Level)); - AddLocToRecord(Loc, SM, PLoc, Record); + AddLocToRecord(Loc, PLoc, Record); if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) { // Emit the category string lazily and get the category ID. @@ -672,15 +652,11 @@ void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc, Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message); } -void -SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, - ArrayRef<clang::CharSourceRange> Ranges, - const SourceManager *SM, - DiagOrStoredDiag D) { - Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D); +void SDiagsRenderer::emitDiagnosticMessage( + FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, + StringRef Message, ArrayRef<clang::CharSourceRange> Ranges, + DiagOrStoredDiag D) { + Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, D); } void SDiagsWriter::EnterDiagBlock() { @@ -733,20 +709,18 @@ void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, } } -void SDiagsRenderer::emitCodeContext(SourceLocation Loc, +void SDiagsRenderer::emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange> &Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) { - Writer.EmitCodeContext(Ranges, Hints, SM); + ArrayRef<FixItHint> Hints) { + Writer.EmitCodeContext(Ranges, Hints, Loc.getManager()); } -void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) { +void SDiagsRenderer::emitNote(FullSourceLoc Loc, StringRef Message) { Writer.EnterDiagBlock(); - PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc(); - Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, - Message, SM, DiagOrStoredDiag()); + PresumedLoc PLoc = Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(); + Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, Message, + DiagOrStoredDiag()); Writer.ExitDiagBlock(); } diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index a24d5768f558..1e12ea5e597a 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -672,20 +672,16 @@ TextDiagnostic::TextDiagnostic(raw_ostream &OS, TextDiagnostic::~TextDiagnostic() {} -void -TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, - ArrayRef<clang::CharSourceRange> Ranges, - const SourceManager *SM, - DiagOrStoredDiag D) { +void TextDiagnostic::emitDiagnosticMessage( + FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, + StringRef Message, ArrayRef<clang::CharSourceRange> Ranges, + DiagOrStoredDiag D) { uint64_t StartOfLocationInfo = OS.tell(); // Emit the location of this particular diagnostic. if (Loc.isValid()) - emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM); - + emitDiagnosticLoc(Loc, PLoc, Level, Ranges); + if (DiagOpts->ShowColors) OS.resetColor(); @@ -787,17 +783,16 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) { /// This includes extracting as much location information as is present for /// the diagnostic and printing it, as well as any include stack or source /// ranges necessary. -void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, +void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) { + ArrayRef<CharSourceRange> Ranges) { if (PLoc.isInvalid()) { // At least print the file name if available: - FileID FID = SM.getFileID(Loc); + FileID FID = Loc.getFileID(); if (FID.isValid()) { - const FileEntry* FE = SM.getFileEntryForID(FID); + const FileEntry *FE = Loc.getFileEntry(); if (FE && FE->isValid()) { - emitFilename(FE->getName(), SM); + emitFilename(FE->getName(), Loc.getManager()); if (FE->isInPCH()) OS << " (in PCH)"; OS << ": "; @@ -813,7 +808,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, if (DiagOpts->ShowColors) OS.changeColor(savedColor, true); - emitFilename(PLoc.getFilename(), SM); + emitFilename(PLoc.getFilename(), Loc.getManager()); switch (DiagOpts->getFormat()) { case DiagnosticOptions::Clang: OS << ':' << LineNo; break; case DiagnosticOptions::MSVC: OS << '(' << LineNo; break; @@ -848,8 +843,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, } if (DiagOpts->ShowSourceRanges && !Ranges.empty()) { - FileID CaretFileID = - SM.getFileID(SM.getExpansionLoc(Loc)); + FileID CaretFileID = Loc.getExpansionLoc().getFileID(); bool PrintedRange = false; for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(), @@ -858,8 +852,10 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, // Ignore invalid ranges. if (!RI->isValid()) continue; - SourceLocation B = SM.getExpansionLoc(RI->getBegin()); - SourceLocation E = SM.getExpansionLoc(RI->getEnd()); + FullSourceLoc B = + FullSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc(); + FullSourceLoc E = + FullSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc(); // If the End location and the start location are the same and are a // macro location, then the range was something that came from a @@ -867,10 +863,12 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, // best we can do is to highlight the range. If this is a // function-like macro, we'd also like to highlight the arguments. if (B == E && RI->getEnd().isMacroID()) - E = SM.getExpansionRange(RI->getEnd()).second; + E = FullSourceLoc(RI->getEnd(), Loc.getManager()) + .getExpansionRange() + .second; - std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); - std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); + std::pair<FileID, unsigned> BInfo = B.getDecomposedLoc(); + std::pair<FileID, unsigned> EInfo = E.getDecomposedLoc(); // If the start or end of the range is in another file, just discard // it. @@ -881,13 +879,10 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, // tokens. unsigned TokSize = 0; if (RI->isTokenRange()) - TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts); + TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts); - OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':' - << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' - << SM.getLineNumber(EInfo.first, EInfo.second) << ':' - << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) - << '}'; + OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-' + << E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}'; PrintedRange = true; } @@ -897,9 +892,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, OS << ' '; } -void TextDiagnostic::emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc, - const SourceManager &SM) { +void TextDiagnostic::emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) { if (DiagOpts->ShowLocation && PLoc.isValid()) OS << "In file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; @@ -907,9 +900,8 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc, OS << "In included file:\n"; } -void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { +void TextDiagnostic::emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) { if (DiagOpts->ShowLocation && PLoc.isValid()) OS << "In module '" << ModuleName << "' imported from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; @@ -917,10 +909,9 @@ void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, OS << "In module '" << ModuleName << "':\n"; } -void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc, +void TextDiagnostic::emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { + StringRef ModuleName) { if (DiagOpts->ShowLocation && PLoc.isValid()) OS << "While building module '" << ModuleName << "' imported from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; @@ -1134,10 +1125,8 @@ static std::string buildFixItInsertionLine(unsigned LineNo, /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. void TextDiagnostic::emitSnippetAndCaret( - SourceLocation Loc, DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) { + FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, ArrayRef<FixItHint> Hints) { assert(Loc.isValid() && "must have a valid source location here"); assert(Loc.isFileID() && "must have a file location here"); @@ -1154,18 +1143,18 @@ void TextDiagnostic::emitSnippetAndCaret( return; // Decompose the location into a FID/Offset pair. - std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + std::pair<FileID, unsigned> LocInfo = Loc.getDecomposedLoc(); FileID FID = LocInfo.first; - unsigned CaretFileOffset = LocInfo.second; + const SourceManager &SM = Loc.getManager(); // Get information about the buffer it points into. bool Invalid = false; - StringRef BufData = SM.getBufferData(FID, &Invalid); + StringRef BufData = Loc.getBufferData(&Invalid); if (Invalid) return; - unsigned CaretLineNo = SM.getLineNumber(FID, CaretFileOffset); - unsigned CaretColNo = SM.getColumnNumber(FID, CaretFileOffset); + unsigned CaretLineNo = Loc.getLineNumber(); + unsigned CaretColNo = Loc.getColumnNumber(); // Arbitrarily stop showing snippets when the line is too long. static const size_t MaxLineLengthToPrint = 4096; diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 17646b48e23d..5dd3252d5b1e 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -150,10 +150,9 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level, "Unexpected diagnostic with no source manager"); assert(TextDiag && "Unexpected diagnostic outside source file processing"); - TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(), - Info.getRanges(), - Info.getFixItHints(), - &Info.getSourceManager()); + TextDiag->emitDiagnostic( + FullSourceLoc(Info.getLocation(), Info.getSourceManager()), Level, + DiagMessageStream.str(), Info.getRanges(), Info.getFixItHints()); OS.flush(); } diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 018d59e5e871..40f78ce25ceb 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -2710,7 +2710,8 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, // If the module map file wasn't already entered, do so now. if (ID.isInvalid()) { - auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; + auto FileCharacter = + IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index a6bfc32e2213..8af9a50cc204 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -1315,6 +1315,8 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) { .Case("cxx_binary_literals", true) .Case("cxx_init_captures", LangOpts.CPlusPlus11) .Case("cxx_variable_templates", LangOpts.CPlusPlus) + // Miscellaneous language extensions + .Case("overloadable_unmarked", true) .Default(false); } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d0ce9fc89583..07054546f42f 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -71,11 +71,18 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } +/// \brief Normalizes an attribute name by dropping prefixed and suffixed __. +static StringRef normalizeAttrName(StringRef Name) { + if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) + return Name.drop_front(2).drop_back(2); + return Name; +} + /// isAttributeLateParsed - Return true if the attribute has arguments that /// require late parsing. static bool isAttributeLateParsed(const IdentifierInfo &II) { #define CLANG_ATTR_LATE_PARSED_LIST - return llvm::StringSwitch<bool>(II.getName()) + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) #include "clang/Parse/AttrParserStringSwitches.inc" .Default(false); #undef CLANG_ATTR_LATE_PARSED_LIST @@ -200,13 +207,6 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } } -/// \brief Normalizes an attribute name by dropping prefixed and suffixed __. -static StringRef normalizeAttrName(StringRef Name) { - if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) - Name = Name.drop_front(2).drop_back(2); - return Name; -} - /// \brief Determine whether the given attribute has an identifier argument. static bool attributeHasIdentifierArg(const IdentifierInfo &II) { #define CLANG_ATTR_IDENTIFIER_ARG_LIST @@ -4319,8 +4319,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } - if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) - ParseEnumBody(StartLoc, TagDecl); + if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) { + Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl; + ParseEnumBody(StartLoc, D); + if (SkipBody.CheckSameAsPrevious && + !Actions.ActOnDuplicateDefinition(DS, TagDecl, SkipBody)) { + DS.SetTypeSpecError(); + return; + } + } if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, @@ -4392,11 +4399,9 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { } // Install the enumerator constant into EnumDecl. - Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl, - LastEnumConstDecl, - IdentLoc, Ident, - attrs.getList(), EqualLoc, - AssignedVal.get()); + Decl *EnumConstDecl = Actions.ActOnEnumConstant( + getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, + attrs.getList(), EqualLoc, AssignedVal.get()); EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index a724fa242268..2301284b7f43 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1910,12 +1910,22 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, else if (getLangOpts().CPlusPlus) ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); - else - ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); + else { + Decl *D = + SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get(); + // Parse the definition body. + ParseStructUnionBody(StartLoc, TagType, D); + if (SkipBody.CheckSameAsPrevious && + !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), + SkipBody)) { + DS.SetTypeSpecError(); + return; + } + } } if (!TagOrTempResult.isInvalid()) - // Delayed proccessing of attributes. + // Delayed processing of attributes. Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); const char *PrevSpec = nullptr; diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 934e13e72d05..fd2d07957c2b 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -305,10 +305,14 @@ static bool isThrowCaught(const CXXThrowExpr *Throw, CaughtType = CaughtType->castAs<ReferenceType>() ->getPointeeType() ->getUnqualifiedDesugaredType(); + if (ThrowType->isPointerType() && CaughtType->isPointerType()) { + ThrowType = ThrowType->getPointeeType()->getUnqualifiedDesugaredType(); + CaughtType = CaughtType->getPointeeType()->getUnqualifiedDesugaredType(); + } if (CaughtType == ThrowType) return true; const CXXRecordDecl *CaughtAsRecordType = - CaughtType->getPointeeCXXRecordDecl(); + CaughtType->getAsCXXRecordDecl(); const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl(); if (CaughtAsRecordType && ThrowTypeAsRecordType) return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 007a5e483e6c..34f5e26be810 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1688,7 +1688,8 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) { QT, OpenCLTypeExtMap); } -bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) { - return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "", +bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) { + IdentifierInfo *FnName = D.getIdentifier(); + return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName, OpenCLDeclExtMap, 1, D.getSourceRange()); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index b794628db738..845c4bf61b7a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6000,6 +6000,7 @@ shouldNotPrintDirectly(const ASTContext &Context, while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) { StringRef Name = UserTy->getDecl()->getName(); QualType CastTy = llvm::StringSwitch<QualType>(Name) + .Case("CFIndex", Context.LongTy) .Case("NSInteger", Context.LongTy) .Case("NSUInteger", Context.UnsignedLongTy) .Case("SInt32", Context.IntTy) @@ -9935,6 +9936,28 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) { ::CheckBoolLikeConversion(*this, E, CC); } +/// Diagnose when expression is an integer constant expression and its evaluation +/// results in integer overflow +void Sema::CheckForIntOverflow (Expr *E) { + // Use a work list to deal with nested struct initializers. + SmallVector<Expr *, 2> Exprs(1, E); + + do { + Expr *E = Exprs.pop_back_val(); + + if (isa<BinaryOperator>(E->IgnoreParenCasts())) { + E->IgnoreParenCasts()->EvaluateForOverflow(Context); + continue; + } + + if (auto InitList = dyn_cast<InitListExpr>(E)) + Exprs.append(InitList->inits().begin(), InitList->inits().end()); + + if (isa<ObjCBoxedExpr>(E)) + E->IgnoreParenCasts()->EvaluateForOverflow(Context); + } while (!Exprs.empty()); +} + namespace { /// \brief Visitor for expressions which looks for unsequenced operations on the /// same object. @@ -10436,7 +10459,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, if (!E->isInstantiationDependent()) CheckUnsequencedOperations(E); if (!IsConstexpr && !E->isValueDependent()) - E->EvaluateForOverflow(Context); + CheckForIntOverflow(E); DiagnoseMisalignedMembers(); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e340456bc6da..ef8a408f90de 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1327,15 +1327,17 @@ void Sema::ActOnExitFunctionContext() { /// overloaded function declaration or has the "overloadable" /// attribute. static bool AllowOverloadingOfFunction(LookupResult &Previous, - ASTContext &Context) { + ASTContext &Context, + const FunctionDecl *New) { if (Context.getLangOpts().CPlusPlus) return true; if (Previous.getResultKind() == LookupResult::FoundOverloaded) return true; - return (Previous.getResultKind() == LookupResult::Found - && Previous.getFoundDecl()->hasAttr<OverloadableAttr>()); + return Previous.getResultKind() == LookupResult::Found && + (Previous.getFoundDecl()->hasAttr<OverloadableAttr>() || + New->hasAttr<OverloadableAttr>()); } /// Add this decl to the scope shadowed decl chains. @@ -2933,6 +2935,41 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, New->dropAttr<InternalLinkageAttr>(); } + if (!getLangOpts().CPlusPlus) { + bool OldOvl = Old->hasAttr<OverloadableAttr>(); + if (OldOvl != New->hasAttr<OverloadableAttr>() && !Old->isImplicit()) { + Diag(New->getLocation(), diag::err_attribute_overloadable_mismatch) + << New << OldOvl; + + // Try our best to find a decl that actually has the overloadable + // attribute for the note. In most cases (e.g. programs with only one + // broken declaration/definition), this won't matter. + // + // FIXME: We could do this if we juggled some extra state in + // OverloadableAttr, rather than just removing it. + const Decl *DiagOld = Old; + if (OldOvl) { + auto OldIter = llvm::find_if(Old->redecls(), [](const Decl *D) { + const auto *A = D->getAttr<OverloadableAttr>(); + return A && !A->isImplicit(); + }); + // If we've implicitly added *all* of the overloadable attrs to this + // chain, emitting a "previous redecl" note is pointless. + DiagOld = OldIter == Old->redecls_end() ? nullptr : *OldIter; + } + + if (DiagOld) + Diag(DiagOld->getLocation(), + diag::note_attribute_overloadable_prev_overload) + << OldOvl; + + if (OldOvl) + New->addAttr(OverloadableAttr::CreateImplicit(Context)); + else + New->dropAttr<OverloadableAttr>(); + } + } + // If a function is first declared with a calling convention, but is later // declared or defined without one, all following decls assume the calling // convention of the first. @@ -9179,6 +9216,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool Redeclaration = false; NamedDecl *OldDecl = nullptr; + bool MayNeedOverloadableChecks = false; // Merge or overload the declaration with an existing declaration of // the same name, if appropriate. @@ -9187,13 +9225,14 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // a declaration that requires merging. If it's an overload, // there's no more work to do here; we'll just add the new // function to the scope. - if (!AllowOverloadingOfFunction(Previous, Context)) { + if (!AllowOverloadingOfFunction(Previous, Context, NewFD)) { NamedDecl *Candidate = Previous.getRepresentativeDecl(); if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) { Redeclaration = true; OldDecl = Candidate; } } else { + MayNeedOverloadableChecks = true; switch (CheckOverload(S, NewFD, Previous, OldDecl, /*NewIsUsingDecl*/ false)) { case Ovl_Match: @@ -9208,18 +9247,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Redeclaration = false; break; } - - if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { - // If a function name is overloadable in C, then every function - // with that name must be marked "overloadable". - Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) - << Redeclaration << NewFD; - NamedDecl *OverloadedDecl = - Redeclaration ? OldDecl : Previous.getRepresentativeDecl(); - Diag(OverloadedDecl->getLocation(), - diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); - } } } @@ -9234,15 +9261,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, MergeTypeWithPrevious = false; // ... except in the presence of __attribute__((overloadable)). - if (OldDecl->hasAttr<OverloadableAttr>()) { - if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { - Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) - << Redeclaration << NewFD; - Diag(Previous.getFoundDecl()->getLocation(), - diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); - } + if (OldDecl->hasAttr<OverloadableAttr>() || + NewFD->hasAttr<OverloadableAttr>()) { if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) { + MayNeedOverloadableChecks = true; Redeclaration = false; OldDecl = nullptr; } @@ -9337,6 +9359,29 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, NewFD->setAccess(OldDecl->getAccess()); } } + } else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks && + !NewFD->getAttr<OverloadableAttr>()) { + assert((Previous.empty() || + llvm::any_of(Previous, + [](const NamedDecl *ND) { + return ND->hasAttr<OverloadableAttr>(); + })) && + "Non-redecls shouldn't happen without overloadable present"); + + auto OtherUnmarkedIter = llvm::find_if(Previous, [](const NamedDecl *ND) { + const auto *FD = dyn_cast<FunctionDecl>(ND); + return FD && !FD->hasAttr<OverloadableAttr>(); + }); + + if (OtherUnmarkedIter != Previous.end()) { + Diag(NewFD->getLocation(), + diag::err_attribute_overloadable_multiple_unmarked_overloads); + Diag((*OtherUnmarkedIter)->getLocation(), + diag::note_attribute_overloadable_prev_overload) + << false; + + NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); + } } // Semantic checking for this function declaration (in isolation). @@ -11100,9 +11145,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { bool IsGlobal = GlobalStorage && !var->isStaticLocal(); QualType baseType = Context.getBaseElementType(type); - if (!var->getDeclContext()->isDependentContext() && - Init && !Init->isValueDependent()) { - + if (Init && !Init->isValueDependent()) { if (var->isConstexpr()) { SmallVector<PartialDiagnosticAt, 8> Notes; if (!var->evaluateValue(Notes) || !var->isInitICE()) { @@ -11932,7 +11975,7 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, if (canRedefineFunction(Definition, getLangOpts())) return; - // Don't emit an error when this is redifinition of a typo-corrected + // Don't emit an error when this is redefinition of a typo-corrected // definition. if (TypoCorrectedFunctionDefinitions.count(Definition)) return; @@ -13190,6 +13233,55 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (TUK == TUK_Friend || TUK == TUK_Reference) Redecl = NotForRedeclaration; + /// Create a new tag decl in C/ObjC. Since the ODR-like semantics for ObjC/C + /// implemented asks for structural equivalence checking, the returned decl + /// here is passed back to the parser, allowing the tag body to be parsed. + auto createTagFromNewDecl = [&]() -> TagDecl * { + assert(!getLangOpts().CPlusPlus && "not meant for C++ usage"); + // If there is an identifier, use the location of the identifier as the + // location of the decl, otherwise use the location of the struct/union + // keyword. + SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; + TagDecl *New = nullptr; + + if (Kind == TTK_Enum) { + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr, + ScopedEnum, ScopedEnumUsesClassTag, + !EnumUnderlying.isNull()); + // If this is an undefined enum, bail. + if (TUK != TUK_Definition && !Invalid) + return nullptr; + if (EnumUnderlying) { + EnumDecl *ED = cast<EnumDecl>(New); + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo *>()) + ED->setIntegerTypeSourceInfo(TI); + else + ED->setIntegerType(QualType(EnumUnderlying.get<const Type *>(), 0)); + ED->setPromotionType(ED->getIntegerType()); + } + } else { // struct/union + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + nullptr); + } + + if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) { + // Add alignment attributes if necessary; these attributes are checked + // when the ASTContext lays out the structure. + // + // It is important for implementing the correct semantics that this + // happen here (in ActOnTag). The #pragma pack stack is + // maintained as a result of parser callbacks which can occur at + // many points during the parsing of a struct declaration (because + // the #pragma tokens are effectively skipped over during the + // parsing of the struct). + if (TUK == TUK_Definition) { + AddAlignmentAttributesForRecord(RD); + AddMsStructLayoutForRecord(RD); + } + } + return New; + }; + LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -13595,16 +13687,28 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TSK_ExplicitSpecialization; } + // Note that clang allows ODR-like semantics for ObjC/C, i.e., do + // not keep more that one definition around (merge them). However, + // ensure the decl passes the structural compatibility check in + // C11 6.2.7/1 (or 6.1.2.6/1 in C89). NamedDecl *Hidden = nullptr; - if (SkipBody && getLangOpts().CPlusPlus && - !hasVisibleDefinition(Def, &Hidden)) { + if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { // There is a definition of this tag, but it is not visible. We // explicitly make use of C++'s one definition rule here, and // assume that this definition is identical to the hidden one // we already have. Make the existing definition visible and // use it in place of this one. - SkipBody->ShouldSkip = true; - makeMergedDefinitionVisible(Hidden); + if (!getLangOpts().CPlusPlus) { + // Postpone making the old definition visible until after we + // complete parsing the new one and do the structural + // comparison. + SkipBody->CheckSameAsPrevious = true; + SkipBody->New = createTagFromNewDecl(); + SkipBody->Previous = Hidden; + } else { + SkipBody->ShouldSkip = true; + makeMergedDefinitionVisible(Hidden); + } return Def; } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't @@ -13832,7 +13936,7 @@ CreateNewDecl: // the ASTContext lays out the structure. // // It is important for implementing the correct semantics that this - // happen here (in act on tag decl). The #pragma pack stack is + // happen here (in ActOnTag). The #pragma pack stack is // maintained as a result of parser callbacks which can occur at // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the @@ -13968,6 +14072,16 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { AddPushedVisibilityAttribute(Tag); } +bool Sema::ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev, + SkipBodyInfo &SkipBody) { + if (!hasStructuralCompatLayout(Prev, SkipBody.New)) + return false; + + // Make the previous decl visible. + makeMergedDefinitionVisible(SkipBody.Previous); + return true; +} + Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { assert(isa<ObjCContainerDecl>(IDecl) && "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); @@ -15389,7 +15503,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // different from T: // - every enumerator of every member of class T that is an unscoped // enumerated type - if (!TheEnumDecl->isScoped()) + if (getLangOpts().CPlusPlus && !TheEnumDecl->isScoped()) DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(), DeclarationNameInfo(Id, IdLoc)); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e8503427536d..1929bc539188 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6571,7 +6571,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } -// Helper for delayed proccessing TransparentUnion attribute. +// Helper for delayed processing TransparentUnion attribute. void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { for (const AttributeList *Attr = AttrList; Attr; Attr = Attr->getNext()) if (Attr->getKind() == AttributeList::AT_TransparentUnion) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 453ece9d9c4d..e9070881afe4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3778,6 +3778,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (BaseType.isNull()) return true; + TInfo = Context.CreateTypeSourceInfo(BaseType); + DependentNameTypeLoc TL = + TInfo->getTypeLoc().castAs<DependentNameTypeLoc>(); + if (!TL.isNull()) { + TL.setNameLoc(IdLoc); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + } + R.clear(); R.setLookupName(MemberOrBase); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 710ead30790f..a9cf3ec7990b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1646,6 +1646,27 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, return false; } +// Emit a diagnostic if an aligned allocation/deallocation function that is not +// implemented in the standard library is selected. +static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc, bool IsDelete, + Sema &S) { + if (!S.getLangOpts().AlignedAllocationUnavailable) + return; + + // Return if there is a definition. + if (FD.isDefined()) + return; + + bool IsAligned = false; + if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) { + S.Diag(Loc, diag::warn_aligned_allocation_unavailable) + << IsDelete << FD.getType().getAsString() + << S.getASTContext().getTargetInfo().getTriple().str(); + S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable); + } +} + ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, @@ -2023,11 +2044,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorNew); + diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this); } if (OperatorDelete) { if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorDelete); + diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this); } // C++0x [expr.new]p17: @@ -3243,6 +3266,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, PDiag(diag::err_access_dtor) << PointeeElem); } } + + diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, + *this); } CXXDeleteExpr *Result = new (Context) CXXDeleteExpr( @@ -4093,15 +4119,9 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsStandardLayout: case UTT_IsPOD: case UTT_IsLiteral: - ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); - LLVM_FALLTHROUGH; - - // C++1z [meta.unary.prop]: - // T shall be a complete type, cv void, or an array of unknown bound. - case UTT_IsDestructible: - case UTT_IsNothrowDestructible: - case UTT_IsTriviallyDestructible: - // Per the GCC type traits documentation, the same constraints apply to these. + // Per the GCC type traits documentation, T shall be a complete type, cv void, + // or an array of unknown bound. But GCC actually imposes the same constraints + // as above. case UTT_HasNothrowAssign: case UTT_HasNothrowMoveAssign: case UTT_HasNothrowConstructor: @@ -4113,6 +4133,14 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: + ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); + LLVM_FALLTHROUGH; + + // C++1z [meta.unary.prop]: + // T shall be a complete type, cv void, or an array of unknown bound. + case UTT_IsDestructible: + case UTT_IsNothrowDestructible: + case UTT_IsTriviallyDestructible: if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) return true; diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 2b7733d2adbd..49da0e499771 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -412,6 +412,30 @@ public: return false; } + /// Do the check specified in \a Check to all component lists at a given level + /// and return true if any issue is found. + bool checkMappableExprComponentListsForDeclAtLevel( + ValueDecl *VD, unsigned Level, + const llvm::function_ref< + bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, + OpenMPClauseKind)> &Check) { + if (isStackEmpty()) + return false; + + auto StartI = Stack.back().first.begin(); + auto EndI = Stack.back().first.end(); + if (std::distance(StartI, EndI) <= (int)Level) + return false; + std::advance(StartI, Level); + + auto MI = StartI->MappedExprComponents.find(VD); + if (MI != StartI->MappedExprComponents.end()) + for (auto &L : MI->second.Components) + if (Check(L, MI->second.Kind)) + return true; + return false; + } + /// Create a new mappable expression component list associated with a given /// declaration and initialize it with the provided list of components. void addMappableExpressionComponents( @@ -994,9 +1018,8 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) { bool IsVariableUsedInMapClause = false; bool IsVariableAssociatedWithSection = false; - DSAStack->checkMappableExprComponentListsForDecl( - D, /*CurrentRegionOnly=*/true, - [&](OMPClauseMappableExprCommon::MappableExprComponentListRef + DSAStack->checkMappableExprComponentListsForDeclAtLevel( + D, Level, [&](OMPClauseMappableExprCommon::MappableExprComponentListRef MapExprComponents, OpenMPClauseKind WhereFoundClauseKind) { // Only the map clause information influences how a variable is diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 8c8402e75e37..b19dcb2a5099 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -7111,6 +7112,20 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return false; } +bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) { + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; + if (!Suggested) + return false; + + // FIXME: Add a specific mode for C11 6.2.7/1 in StructuralEquivalenceContext + // and isolate from other C++ specific checks. + StructuralEquivalenceContext Ctx( + D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls, + false /*StrictTypeSpelling*/, true /*Complain*/, + true /*ErrorOnTagTypeMismatch*/); + return Ctx.IsStructurallyEquivalent(D, Suggested); +} + /// \brief Determine whether there is any declaration of \p D that was ever a /// definition (perhaps before module merging) and is currently visible. /// \param D The definition of the entity. diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index ef2841849ff6..3aee3c04001d 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -856,7 +856,7 @@ static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II, II.isPoisoned() || (IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) || II.hasRevertedTokenIDToIdentifier() || - (!(IsModule && Reader.getContext().getLangOpts().CPlusPlus) && + (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) && II.getFETokenInfo<void>()); } @@ -1148,7 +1148,7 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, void ASTReader::Error(StringRef Msg) const { Error(diag::err_fe_pch_malformed, Msg); - if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight() && + if (PP.getLangOpts().Modules && !Diags.isDiagnosticInFlight() && !PP.getHeaderSearchInfo().getModuleCachePath().empty()) { Diag(diag::note_module_cache_path) << PP.getHeaderSearchInfo().getModuleCachePath(); @@ -1391,15 +1391,14 @@ bool ASTReader::ReadSLocEntry(int ID) { const DeclID *FirstDecl = F->FileSortedDecls + Record[6]; unsigned NumFileDecls = Record[7]; - if (NumFileDecls) { + if (NumFileDecls && ContextObj) { assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl, NumFileDecls)); } const SrcMgr::ContentCache *ContentCache - = SourceMgr.getOrCreateContentCache(File, - /*isSystemFile=*/FileCharacter != SrcMgr::C_User); + = SourceMgr.getOrCreateContentCache(File, isSystem(FileCharacter)); if (OverriddenBuffer && !ContentCache->BufferOverridden && ContentCache->ContentsEntry == ContentCache->OrigEntry && !ContentCache->getRawBuffer()) { @@ -1697,9 +1696,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, HeaderFileInfo HFI; unsigned Flags = *d++; // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp. - HFI.isImport |= (Flags >> 4) & 0x01; - HFI.isPragmaOnce |= (Flags >> 3) & 0x01; - HFI.DirInfo = (Flags >> 1) & 0x03; + HFI.isImport |= (Flags >> 5) & 0x01; + HFI.isPragmaOnce |= (Flags >> 4) & 0x01; + HFI.DirInfo = (Flags >> 1) & 0x07; HFI.IndexHeaderMapHeader = Flags & 0x01; // FIXME: Find a better way to handle this. Maybe just store a // "has been included" flag? @@ -2029,6 +2028,7 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { R.StoredTime = static_cast<time_t>(Record[2]); R.Overridden = static_cast<bool>(Record[3]); R.Transient = static_cast<bool>(Record[4]); + R.TopLevelModuleMap = static_cast<bool>(Record[5]); R.Filename = Blob; ResolveImportedPath(F, R.Filename); return R; @@ -2614,10 +2614,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // contains any declarations lexically within it (which it always does!). // This usually has no cost, since we very rarely need the lookup map for // the translation unit outside C++. - DeclContext *DC = Context.getTranslationUnitDecl(); - if (DC->hasExternalLexicalStorage() && - !getContext().getLangOpts().CPlusPlus) - DC->setMustBuildLookupTable(); + if (ASTContext *Ctx = ContextObj) { + DeclContext *DC = Ctx->getTranslationUnitDecl(); + if (DC->hasExternalLexicalStorage() && !Ctx->getLangOpts().CPlusPlus) + DC->setMustBuildLookupTable(); + } return Success; } @@ -2706,7 +2707,33 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Read and process a record. Record.clear(); StringRef Blob; - switch ((ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) { + auto RecordType = + (ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob); + + // If we're not loading an AST context, we don't care about most records. + if (!ContextObj) { + switch (RecordType) { + case IDENTIFIER_TABLE: + case IDENTIFIER_OFFSET: + case INTERESTING_IDENTIFIERS: + case STATISTICS: + case PP_CONDITIONAL_STACK: + case PP_COUNTER_VALUE: + case SOURCE_LOCATION_OFFSETS: + case MODULE_OFFSET_MAP: + case SOURCE_MANAGER_LINE_TABLE: + case SOURCE_LOCATION_PRELOADS: + case PPD_ENTITIES_OFFSETS: + case HEADER_SEARCH_TABLE: + case IMPORTED_MODULES: + case MACRO_OFFSET: + break; + default: + continue; + } + } + + switch (RecordType) { default: // Default behavior: ignore. break; @@ -2765,7 +2792,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case TU_UPDATE_LEXICAL: { - DeclContext *TU = Context.getTranslationUnitDecl(); + DeclContext *TU = ContextObj->getTranslationUnitDecl(); LexicalContents Contents( reinterpret_cast<const llvm::support::unaligned_uint32_t *>( Blob.data()), @@ -3455,12 +3482,6 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, unsigned Idx = 0; F.ModuleMapPath = ReadPath(F, Record, Idx); - if (F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule) { - // For an explicitly-loaded module, we don't care whether the original - // module map file exists or matches. - return Success; - } - // Try to resolve ModuleName in the current header search context and // verify that it is found in the same module map file as we saved. If the // top-level AST file is a main file, skip this check because there is no @@ -3667,7 +3688,7 @@ bool ASTReader::loadGlobalIndex() { return false; if (TriedLoadingGlobalIndex || !UseGlobalIndex || - !Context.getLangOpts().Modules) + !PP.getLangOpts().Modules) return true; // Try to load the global index. @@ -3685,7 +3706,7 @@ bool ASTReader::loadGlobalIndex() { } bool ASTReader::isGlobalIndexUnavailable() const { - return Context.getLangOpts().Modules && UseGlobalIndex && + return PP.getLangOpts().Modules && UseGlobalIndex && !hasGlobalIndex() && TriedLoadingGlobalIndex; } @@ -3743,7 +3764,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, Deserializing AnASTFile(this); // Bump the generation number. - unsigned PreviousGeneration = incrementGeneration(Context); + unsigned PreviousGeneration = 0; + if (ContextObj) + PreviousGeneration = incrementGeneration(*ContextObj); unsigned NumModules = ModuleMgr.size(); SmallVector<ImportedModule, 4> Loaded; @@ -3762,7 +3785,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, LoadedSet.insert(IM.Mod); ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, LoadedSet, - Context.getLangOpts().Modules + PP.getLangOpts().Modules ? &PP.getHeaderSearchInfo().getModuleMap() : nullptr); @@ -3858,7 +3881,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, F.ImportLoc = TranslateSourceLocation(*M->ImportedBy, M->ImportLoc); } - if (!Context.getLangOpts().CPlusPlus || + if (!PP.getLangOpts().CPlusPlus || (Type != MK_ImplicitModule && Type != MK_ExplicitModule && Type != MK_PrebuiltModule)) { // Mark all of the identifiers in the identifier table as being out of date, @@ -3915,7 +3938,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, // Might be unnecessary as use declarations are only used to build the // module itself. - InitializeContext(); + if (ContextObj) + InitializeContext(); if (SemaObj) UpdateSema(); @@ -3937,10 +3961,12 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, // For any Objective-C class definitions we have already loaded, make sure // that we load any additional categories. - for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { - loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), - ObjCClassesLoaded[I], - PreviousGeneration); + if (ContextObj) { + for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { + loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), + ObjCClassesLoaded[I], + PreviousGeneration); + } } if (PP.getHeaderSearchInfo() @@ -4320,6 +4346,9 @@ ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) { } void ASTReader::InitializeContext() { + assert(ContextObj && "no context to initialize"); + ASTContext &Context = *ContextObj; + // If there's a listener, notify them that we "read" the translation unit. if (DeserializationListener) DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, @@ -5054,8 +5083,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } case SUBMODULE_REQUIRES: { - CurrentModule->addRequirement(Blob, Record[0], Context.getLangOpts(), - Context.getTargetInfo()); + CurrentModule->addRequirement(Blob, Record[0], PP.getLangOpts(), + PP.getTargetInfo()); break; } @@ -5081,10 +5110,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_INITIALIZERS: + if (!ContextObj) + break; SmallVector<uint32_t, 16> Inits; for (auto &ID : Record) Inits.push_back(getGlobalDeclID(F, ID)); - Context.addLazyModuleInitializers(CurrentModule, Inits); + ContextObj->addLazyModuleInitializers(CurrentModule, Inits); break; } } @@ -5705,6 +5736,8 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { /// location. It is a helper routine for GetType, which deals with reading type /// IDs. QualType ASTReader::readTypeRecord(unsigned Index) { + assert(ContextObj && "reading type with no AST context"); + ASTContext &Context = *ContextObj; RecordLocation Loc = TypeCursorForIndex(Index); BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; @@ -6561,6 +6594,9 @@ ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record, } QualType ASTReader::GetType(TypeID ID) { + assert(ContextObj && "reading type with no AST context"); + ASTContext &Context = *ContextObj; + unsigned FastQuals = ID & Qualifiers::FastMask; unsigned Index = ID >> Qualifiers::FastWidth; @@ -6892,6 +6928,9 @@ ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) { } CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { + assert(ContextObj && "reading base specifiers with no AST context"); + ASTContext &Context = *ContextObj; + RecordLocation Loc = getLocalBitOffset(Offset); BitstreamCursor &Cursor = Loc.F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); @@ -7023,8 +7062,9 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { } Decl *ASTReader::GetExistingDecl(DeclID ID) { + assert(ContextObj && "reading decl with no AST context"); if (ID < NUM_PREDEF_DECL_IDS) { - Decl *D = getPredefinedDecl(Context, (PredefinedDeclIDs)ID); + Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID); if (D) { // Track that we have merged the declaration with ID \p ID into the // pre-existing predefined declaration \p D. @@ -7569,7 +7609,7 @@ IdentifierInfo *ASTReader::get(StringRef Name) { // all interesting declarations, and don't need to use the scope for name // lookups). Perform the lookup in PCH files, though, since we don't build // a complete initial identifier table if we're carrying on from a PCH. - if (Context.getLangOpts().CPlusPlus) { + if (PP.getLangOpts().CPlusPlus) { for (auto F : ModuleMgr.pch_modules()) if (Visitor(*F)) break; @@ -8223,7 +8263,7 @@ ASTReader::getSourceDescriptor(unsigned ID) { return ExternalASTSource::ASTSourceDescriptor(*M); // If there is only a single PCH, return it instead. - // Chained PCH are not suported. + // Chained PCH are not supported. const auto &PCHChain = ModuleMgr.pch_modules(); if (std::distance(std::begin(PCHChain), std::end(PCHChain))) { ModuleFile &MF = ModuleMgr.getPrimaryModule(); @@ -8299,6 +8339,7 @@ ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const { DeclarationName ASTReader::ReadDeclarationName(ModuleFile &F, const RecordData &Record, unsigned &Idx) { + ASTContext &Context = getContext(); DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; switch (Kind) { case DeclarationName::Identifier: @@ -8389,7 +8430,8 @@ void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info, unsigned NumTPLists = Record[Idx++]; Info.NumTemplParamLists = NumTPLists; if (NumTPLists) { - Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists]; + Info.TemplParamLists = + new (getContext()) TemplateParameterList *[NumTPLists]; for (unsigned i = 0; i != NumTPLists; ++i) Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx); } @@ -8398,6 +8440,7 @@ void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info, TemplateName ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record, unsigned &Idx) { + ASTContext &Context = getContext(); TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; switch (Kind) { case TemplateName::Template: @@ -8458,6 +8501,7 @@ TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F, const RecordData &Record, unsigned &Idx, bool Canonicalize) { + ASTContext &Context = getContext(); if (Canonicalize) { // The caller wants a canonical template argument. Sometimes the AST only // wants template arguments in canonical form (particularly as the template @@ -8521,9 +8565,8 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F, Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx)); // TODO: Concepts - TemplateParameterList* TemplateParams = - TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, - Params, RAngleLoc, nullptr); + TemplateParameterList *TemplateParams = TemplateParameterList::Create( + getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr); return TemplateParams; } @@ -8542,11 +8585,11 @@ ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, void ASTReader::ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; - Set.reserve(Context, NumDecls); + Set.reserve(getContext(), NumDecls); while (NumDecls--) { DeclID ID = ReadDeclID(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addLazyDecl(Context, ID, AS); + Set.addLazyDecl(getContext(), ID, AS); } } @@ -8569,6 +8612,7 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, CXXCtorInitializer ** ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx) { + ASTContext &Context = getContext(); unsigned NumInitializers = Record[Idx++]; assert(NumInitializers && "wrote ctor initializers but have no inits"); auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; @@ -8634,6 +8678,7 @@ ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, NestedNameSpecifier * ASTReader::ReadNestedNameSpecifier(ModuleFile &F, const RecordData &Record, unsigned &Idx) { + ASTContext &Context = getContext(); unsigned N = Record[Idx++]; NestedNameSpecifier *NNS = nullptr, *Prev = nullptr; for (unsigned I = 0; I != N; ++I) { @@ -8689,6 +8734,7 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F, NestedNameSpecifierLoc ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx) { + ASTContext &Context = getContext(); unsigned N = Record[Idx++]; NestedNameSpecifierLocBuilder Builder; for (unsigned I = 0; I != N; ++I) { @@ -8810,7 +8856,7 @@ CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, const RecordData &Record, unsigned &Idx) { CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx); - return CXXTemporary::Create(Context, Decl); + return CXXTemporary::Create(getContext(), Decl); } DiagnosticBuilder ASTReader::Diag(unsigned DiagID) const { @@ -8846,6 +8892,7 @@ void ASTReader::ClearSwitchCaseIDs() { } void ASTReader::ReadComments() { + ASTContext &Context = getContext(); std::vector<RawComment *> Comments; for (SmallVectorImpl<std::pair<BitstreamCursor, serialization::ModuleFile *> >::iterator @@ -8915,6 +8962,19 @@ void ASTReader::visitInputFiles(serialization::ModuleFile &MF, } } +void ASTReader::visitTopLevelModuleMaps( + serialization::ModuleFile &MF, + llvm::function_ref<void(const FileEntry *FE)> Visitor) { + unsigned NumInputs = MF.InputFilesLoaded.size(); + for (unsigned I = 0; I < NumInputs; ++I) { + InputFileInfo IFI = readInputFileInfo(MF, I + 1); + if (IFI.TopLevelModuleMap) + // FIXME: This unnecessarily re-reads the InputFileInfo. + if (auto *FE = getInputFile(MF, I + 1).getFile()) + Visitor(FE); + } +} + std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { // If we know the owning module, use it. if (Module *M = D->getImportedOwningModule()) @@ -9514,8 +9574,8 @@ void ASTReader::diagnoseOdrViolations() { break; } - assert( - Context.hasSameType(FirstField->getType(), SecondField->getType())); + assert(getContext().hasSameType(FirstField->getType(), + SecondField->getType())); QualType FirstType = FirstField->getType(); QualType SecondType = SecondField->getType(); @@ -9966,10 +10026,10 @@ void ASTReader::FinishedDeserializing() { ProcessingUpdatesRAIIObj ProcessingUpdates(*this); auto *FPT = Update.second->getType()->castAs<FunctionProtoType>(); auto ESI = FPT->getExtProtoInfo().ExceptionSpec; - if (auto *Listener = Context.getASTMutationListener()) + if (auto *Listener = getContext().getASTMutationListener()) Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second)); for (auto *Redecl : Update.second->redecls()) - Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); + getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); } } @@ -10011,7 +10071,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { } } -ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, +ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context, const PCHContainerReader &PCHContainerRdr, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, StringRef isysroot, bool DisableValidation, @@ -10024,7 +10084,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, : cast<ASTReaderListener>(new PCHValidator(PP, *this))), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP), - Context(Context), + ContextObj(Context), ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr), PCMCache(PP.getPCMCache()), DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot), diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 07ab421cfc51..4d9ddd2ff506 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -126,6 +126,9 @@ namespace clang { void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); void MergeDefinitionData(ObjCInterfaceDecl *D, struct ObjCInterfaceDecl::DefinitionData &&NewDD); + void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data); + void MergeDefinitionData(ObjCProtocolDecl *D, + struct ObjCProtocolDecl::DefinitionData &&NewDD); static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, @@ -216,6 +219,30 @@ namespace clang { TypedefNameForLinkage(nullptr), HasPendingBody(false), IsDeclMarkedUsed(false) {} + template <typename T> static + void AddLazySpecializations(T *D, + SmallVectorImpl<serialization::DeclID>& IDs) { + if (IDs.empty()) + return; + + // FIXME: We should avoid this pattern of getting the ASTContext. + ASTContext &C = D->getASTContext(); + + auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; + + if (auto &Old = LazySpecializations) { + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + std::sort(IDs.begin(), IDs.end()); + IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); + } + + auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; + *Result = IDs.size(); + std::copy(IDs.begin(), IDs.end(), Result + 1); + + LazySpecializations = Result; + } + template <typename DeclT> static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D); static Decl *getMostRecentDeclImpl(...); @@ -244,7 +271,7 @@ namespace clang { void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D); + void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -1045,18 +1072,8 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { IVD->setSynthesize(synth); } -void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { - RedeclarableResult Redecl = VisitRedeclarable(PD); - VisitObjCContainerDecl(PD); - mergeRedeclarable(PD, Redecl); - - if (Record.readInt()) { - // Read the definition. - PD->allocateDefinitionData(); - - // Set the definition data of the canonical declaration, so other - // redeclarations will see it. - PD->getCanonicalDecl()->Data = PD->Data; +void ASTDeclReader::ReadObjCDefinitionData( + struct ObjCProtocolDecl::DefinitionData &Data) { unsigned NumProtoRefs = Record.readInt(); SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; @@ -1067,9 +1084,37 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(ReadSourceLocation()); - PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - Reader.getContext()); + Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs, + ProtoLocs.data(), Reader.getContext()); +} + +void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D, + struct ObjCProtocolDecl::DefinitionData &&NewDD) { + // FIXME: odr checking? +} + +void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { + RedeclarableResult Redecl = VisitRedeclarable(PD); + VisitObjCContainerDecl(PD); + mergeRedeclarable(PD, Redecl); + + if (Record.readInt()) { + // Read the definition. + PD->allocateDefinitionData(); + + ReadObjCDefinitionData(PD->data()); + ObjCProtocolDecl *Canon = PD->getCanonicalDecl(); + if (Canon->Data.getPointer()) { + // If we already have a definition, keep the definition invariant and + // merge the data. + MergeDefinitionData(Canon, std::move(PD->data())); + PD->Data = Canon->Data; + } else { + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + PD->getCanonicalDecl()->Data = PD->Data; + } // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(PD); } else { @@ -1566,8 +1611,8 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.NumExplicitCaptures = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); Lambda.ContextDecl = ReadDeclID(); - Lambda.Captures - = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); + Lambda.Captures = (Capture *)Reader.getContext().Allocate( + sizeof(Capture) * Lambda.NumCaptures); Capture *ToCapture = Lambda.Captures; Lambda.MethodTyInfo = GetTypeSourceInfo(); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { @@ -1950,21 +1995,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { return Redecl; } -static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old, - SmallVectorImpl<DeclID> &IDs) { - assert(!IDs.empty() && "no IDs to add to list"); - if (Old) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); - std::sort(IDs.begin(), IDs.end()); - IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); - } - - auto *Result = new (Context) DeclID[1 + IDs.size()]; - *Result = IDs.size(); - std::copy(IDs.begin(), IDs.end(), Result + 1); - return Result; -} - void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); @@ -1973,19 +2003,14 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { // the specializations. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } if (D->getTemplatedDecl()->TemplateOrInstantiation) { // We were loaded before our templated declaration was. We've not set up // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct // it now. - Reader.Context.getInjectedClassNameType( + Reader.getContext().getInjectedClassNameType( D->getTemplatedDecl(), D->getInjectedClassNameSpecialization()); } } @@ -2005,12 +2030,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { // the specializations. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } } @@ -2116,12 +2136,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // This FunctionTemplateDecl owns a CommonPtr; read it. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } } @@ -2472,8 +2487,8 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) { if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) if (T *Existing = ExistingRes) - Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D), - Existing->getCanonicalDecl()); + Reader.getContext().setPrimaryMergedDecl(static_cast<T *>(D), + Existing->getCanonicalDecl()); } void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { @@ -2509,6 +2524,7 @@ void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { Attr *New = nullptr; attr::Kind Kind = (attr::Kind)Record.readInt(); SourceRange Range = Record.readSourceRange(); + ASTContext &Context = getContext(); #include "clang/Serialization/AttrPCHRead.inc" @@ -2907,7 +2923,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, // commit to DC being the canonical definition now, and will fix this when // we load the update record. if (!DD) { - DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD); + DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD); RD->IsCompleteDefinition = true; RD->DefinitionData = DD; RD->getCanonicalDecl()->DefinitionData = DD; @@ -3352,6 +3368,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc); unsigned Code = DeclsCursor.ReadCode(); + ASTContext &Context = getContext(); Decl *D = nullptr; switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) { case DECL_CONTEXT_LEXICAL: @@ -3652,7 +3669,7 @@ void ASTReader::PassInterestingDeclsToConsumer() { while (!PotentiallyInterestingDecls.empty()) { InterestingDecl D = PotentiallyInterestingDecls.front(); PotentiallyInterestingDecls.pop_front(); - if (isConsumerInterestedIn(Context, D.getDecl(), D.hasPendingBody())) + if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody())) PassInterestingDeclToConsumer(D.getDecl()); } } @@ -3665,6 +3682,9 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); + + llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; + if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); @@ -3674,7 +3694,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // to isConsumerInterestedIn because it is unsafe to call in the // current ASTReader state. bool WasInteresting = - Record.JustLoaded || isConsumerInterestedIn(Context, D, false); + Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; uint64_t Offset = FileAndOffset.second; @@ -3689,18 +3709,29 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, SourceLocation()); - Reader.UpdateDecl(D); + Reader.UpdateDecl(D, PendingLazySpecializationIDs); // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. if (!WasInteresting && - isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) { + isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) { PotentiallyInterestingDecls.push_back( InterestingDecl(D, Reader.hasPendingBody())); WasInteresting = true; } } } + // Add the lazy specializations to the template. + assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) || + isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) && + "Must not have pending specializations"); + if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); + else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs); + else if (auto *VTD = dyn_cast<VarTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs); + PendingLazySpecializationIDs.clear(); // Load the pending visible updates for this decl context, if it has any. auto I = PendingVisibleUpdates.find(ID); @@ -3897,7 +3928,8 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D) { +void ASTDeclReader::UpdateDecl(Decl *D, + llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { @@ -3913,8 +3945,8 @@ void ASTDeclReader::UpdateDecl(Decl *D) { } case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: - // It will be added to the template's specializations set when loaded. - (void)Record.readDecl(); + // It will be added to the template's lazy specialization set. + PendingLazySpecializationIDs.push_back(ReadDeclID()); break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { @@ -4083,7 +4115,7 @@ void ASTDeclReader::UpdateDecl(Decl *D) { // FIXME: If the exception specification is already present, check that it // matches. if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { - FD->setType(Reader.Context.getFunctionType( + FD->setType(Reader.getContext().getFunctionType( FPT->getReturnType(), FPT->getParamTypes(), FPT->getExtProtoInfo().withExceptionSpec(ESI))); @@ -4101,28 +4133,31 @@ void ASTDeclReader::UpdateDecl(Decl *D) { for (auto *Redecl : merged_redecls(D)) { // FIXME: If the return type is already deduced, check that it matches. FunctionDecl *FD = cast<FunctionDecl>(Redecl); - Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType); + Reader.getContext().adjustDeducedFunctionResultType(FD, + DeducedResultType); } break; } case UPD_DECL_MARKED_USED: { // Maintain AST consistency: any later redeclarations are used too. - D->markUsed(Reader.Context); + D->markUsed(Reader.getContext()); break; } case UPD_MANGLING_NUMBER: - Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record.readInt()); + Reader.getContext().setManglingNumber(cast<NamedDecl>(D), + Record.readInt()); break; case UPD_STATIC_LOCAL_NUMBER: - Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record.readInt()); + Reader.getContext().setStaticLocalNumber(cast<VarDecl>(D), + Record.readInt()); break; case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: - D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( - Reader.Context, ReadSourceRange())); + D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(), + ReadSourceRange())); break; case UPD_DECL_EXPORTED: { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 3d314a85ff17..afee50ffa3b9 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -2954,6 +2954,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } + ASTContext &Context = getContext(); Stmt *S = nullptr; bool Finished = false; bool IsStmtReference = false; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 1c0db14ced14..c6129d326cb6 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1692,6 +1692,7 @@ namespace { bool IsSystemFile; bool IsTransient; bool BufferOverridden; + bool IsTopLevelModuleMap; }; } // end anonymous namespace @@ -1710,6 +1711,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient + IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev)); @@ -1724,7 +1726,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, // We only care about file entries that were not overridden. if (!SLoc->isFile()) continue; - const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); + const SrcMgr::FileInfo &File = SLoc->getFile(); + const SrcMgr::ContentCache *Cache = File.getContentCache(); if (!Cache->OrigEntry) continue; @@ -1733,6 +1736,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, Entry.IsSystemFile = Cache->IsSystemFile; Entry.IsTransient = Cache->IsTransient; Entry.BufferOverridden = Cache->BufferOverridden; + Entry.IsTopLevelModuleMap = isModuleMap(File.getFileCharacteristic()) && + File.getIncludeLoc().isInvalid(); if (Cache->IsSystemFile) SortedFiles.push_back(Entry); else @@ -1763,7 +1768,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, (uint64_t)Entry.File->getSize(), (uint64_t)getTimestampForOutput(Entry.File), Entry.BufferOverridden, - Entry.IsTransient}; + Entry.IsTransient, + Entry.IsTopLevelModuleMap}; EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); } @@ -1798,7 +1804,7 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives // FileEntry fields. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID @@ -1817,7 +1823,7 @@ static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob return Stream.EmitAbbrev(std::move(Abbrev)); @@ -1925,8 +1931,8 @@ namespace { endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.HFI.isImport << 4) - | (Data.HFI.isPragmaOnce << 3) + unsigned char Flags = (Data.HFI.isImport << 5) + | (Data.HFI.isPragmaOnce << 4) | (Data.HFI.DirInfo << 1) | Data.HFI.IndexHeaderMapHeader; LE.write<uint8_t>(Flags); diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 26bf597bd950..7f9a00ff876d 100644 --- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -45,6 +45,8 @@ class UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > { mutable Optional<uint64_t> Val_O_CREAT; public: + DefaultBool CheckMisuse, CheckPortability; + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; void CheckOpen(CheckerContext &C, const CallExpr *CE) const; @@ -437,29 +439,42 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE, if (FName.empty()) return; - SubChecker SC = - llvm::StringSwitch<SubChecker>(FName) - .Case("open", &UnixAPIChecker::CheckOpen) - .Case("openat", &UnixAPIChecker::CheckOpenAt) - .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce) - .Case("calloc", &UnixAPIChecker::CheckCallocZero) - .Case("malloc", &UnixAPIChecker::CheckMallocZero) - .Case("realloc", &UnixAPIChecker::CheckReallocZero) - .Case("reallocf", &UnixAPIChecker::CheckReallocfZero) - .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero) - .Case("__builtin_alloca_with_align", - &UnixAPIChecker::CheckAllocaWithAlignZero) - .Case("valloc", &UnixAPIChecker::CheckVallocZero) - .Default(nullptr); - - if (SC) - (this->*SC)(C, CE); + if (CheckMisuse) { + if (SubChecker SC = + llvm::StringSwitch<SubChecker>(FName) + .Case("open", &UnixAPIChecker::CheckOpen) + .Case("openat", &UnixAPIChecker::CheckOpenAt) + .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce) + .Default(nullptr)) { + (this->*SC)(C, CE); + } + } + if (CheckPortability) { + if (SubChecker SC = + llvm::StringSwitch<SubChecker>(FName) + .Case("calloc", &UnixAPIChecker::CheckCallocZero) + .Case("malloc", &UnixAPIChecker::CheckMallocZero) + .Case("realloc", &UnixAPIChecker::CheckReallocZero) + .Case("reallocf", &UnixAPIChecker::CheckReallocfZero) + .Cases("alloca", "__builtin_alloca", + &UnixAPIChecker::CheckAllocaZero) + .Case("__builtin_alloca_with_align", + &UnixAPIChecker::CheckAllocaWithAlignZero) + .Case("valloc", &UnixAPIChecker::CheckVallocZero) + .Default(nullptr)) { + (this->*SC)(C, CE); + } + } } //===----------------------------------------------------------------------===// // Registration. //===----------------------------------------------------------------------===// -void ento::registerUnixAPIChecker(CheckerManager &mgr) { - mgr.registerChecker<UnixAPIChecker>(); -} +#define REGISTER_CHECKER(Name) \ + void ento::registerUnixAPI##Name##Checker(CheckerManager &mgr) { \ + mgr.registerChecker<UnixAPIChecker>()->Check##Name = true; \ + } + +REGISTER_CHECKER(Misuse) +REGISTER_CHECKER(Portability) diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp index 77c5b547ca09..0e835579e04e 100644 --- a/lib/Tooling/CompilationDatabase.cpp +++ b/lib/Tooling/CompilationDatabase.cpp @@ -255,10 +255,12 @@ static bool stripPositionalArgs(std::vector<const char *> Args, CompileJobAnalyzer CompileAnalyzer; for (const auto &Cmd : Jobs) { - // Collect only for Assemble jobs. If we do all jobs we get duplicates - // since Link jobs point to Assemble jobs as inputs. - if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass) + // Collect only for Assemble and Compile jobs. If we do all jobs we get + // duplicates since Link jobs point to Assemble jobs as inputs. + if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass || + Cmd.getSource().getKind() == driver::Action::CompileJobClass) { CompileAnalyzer.run(&Cmd.getSource()); + } } if (CompileAnalyzer.Inputs.empty()) { diff --git a/lib/Tooling/Refactoring/AtomicChange.cpp b/lib/Tooling/Refactoring/AtomicChange.cpp index 321bbfa2866a..79dd346acf72 100644 --- a/lib/Tooling/Refactoring/AtomicChange.cpp +++ b/lib/Tooling/Refactoring/AtomicChange.cpp @@ -12,7 +12,6 @@ #include "llvm/Support/YAMLTraits.h" #include <string> -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string) LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::AtomicChange) namespace { diff --git a/lib/Tooling/Refactoring/CMakeLists.txt b/lib/Tooling/Refactoring/CMakeLists.txt index b2f9b4f4c0cd..288582fc1b6b 100644 --- a/lib/Tooling/Refactoring/CMakeLists.txt +++ b/lib/Tooling/Refactoring/CMakeLists.txt @@ -5,8 +5,16 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangToolingRefactor AtomicChange.cpp + Rename/RenamingAction.cpp + Rename/USRFinder.cpp + Rename/USRFindingAction.cpp + Rename/USRLocFinder.cpp LINK_LIBS + clangAST + clangASTMatchers clangBasic + clangIndex + clangLex clangToolingCore ) diff --git a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp new file mode 100644 index 000000000000..de6aba944a4a --- /dev/null +++ b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp @@ -0,0 +1,134 @@ +//===--- RenamingAction.cpp - Clang refactoring library -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides an action to rename every symbol at a point. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Refactoring/Rename/RenamingAction.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/FileManager.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/Rename/USRLocFinder.h" +#include "clang/Tooling/Tooling.h" +#include <string> +#include <vector> + +using namespace llvm; + +namespace clang { +namespace tooling { + +class RenamingASTConsumer : public ASTConsumer { +public: + RenamingASTConsumer( + const std::vector<std::string> &NewNames, + const std::vector<std::string> &PrevNames, + const std::vector<std::vector<std::string>> &USRList, + std::map<std::string, tooling::Replacements> &FileToReplaces, + bool PrintLocations) + : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList), + FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {} + + void HandleTranslationUnit(ASTContext &Context) override { + for (unsigned I = 0; I < NewNames.size(); ++I) + HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]); + } + + void HandleOneRename(ASTContext &Context, const std::string &NewName, + const std::string &PrevName, + const std::vector<std::string> &USRs) { + const SourceManager &SourceMgr = Context.getSourceManager(); + std::vector<SourceLocation> RenamingCandidates; + std::vector<SourceLocation> NewCandidates; + + NewCandidates = tooling::getLocationsOfUSRs( + USRs, PrevName, Context.getTranslationUnitDecl()); + RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(), + NewCandidates.end()); + + unsigned PrevNameLen = PrevName.length(); + for (const auto &Loc : RenamingCandidates) { + if (PrintLocations) { + FullSourceLoc FullLoc(Loc, SourceMgr); + errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc) + << ":" << FullLoc.getSpellingLineNumber() << ":" + << FullLoc.getSpellingColumnNumber() << "\n"; + } + // FIXME: better error handling. + tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName); + llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace); + if (Err) + llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! " + << llvm::toString(std::move(Err)) << "\n"; + } + } + +private: + const std::vector<std::string> &NewNames, &PrevNames; + const std::vector<std::vector<std::string>> &USRList; + std::map<std::string, tooling::Replacements> &FileToReplaces; + bool PrintLocations; +}; + +// A renamer to rename symbols which are identified by a give USRList to +// new name. +// +// FIXME: Merge with the above RenamingASTConsumer. +class USRSymbolRenamer : public ASTConsumer { +public: + USRSymbolRenamer(const std::vector<std::string> &NewNames, + const std::vector<std::vector<std::string>> &USRList, + std::map<std::string, tooling::Replacements> &FileToReplaces) + : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) { + assert(USRList.size() == NewNames.size()); + } + + void HandleTranslationUnit(ASTContext &Context) override { + for (unsigned I = 0; I < NewNames.size(); ++I) { + // FIXME: Apply AtomicChanges directly once the refactoring APIs are + // ready. + auto AtomicChanges = tooling::createRenameAtomicChanges( + USRList[I], NewNames[I], Context.getTranslationUnitDecl()); + for (const auto AtomicChange : AtomicChanges) { + for (const auto &Replace : AtomicChange.getReplacements()) { + llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace); + if (Err) { + llvm::errs() << "Renaming failed in " << Replace.getFilePath() + << "! " << llvm::toString(std::move(Err)) << "\n"; + } + } + } + } + } + +private: + const std::vector<std::string> &NewNames; + const std::vector<std::vector<std::string>> &USRList; + std::map<std::string, tooling::Replacements> &FileToReplaces; +}; + +std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() { + return llvm::make_unique<RenamingASTConsumer>(NewNames, PrevNames, USRList, + FileToReplaces, PrintLocations); +} + +std::unique_ptr<ASTConsumer> QualifiedRenamingAction::newASTConsumer() { + return llvm::make_unique<USRSymbolRenamer>(NewNames, USRList, FileToReplaces); +} + +} // end namespace tooling +} // end namespace clang diff --git a/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/lib/Tooling/Refactoring/Rename/USRFinder.cpp new file mode 100644 index 000000000000..f36387dafdbf --- /dev/null +++ b/lib/Tooling/Refactoring/Rename/USRFinder.cpp @@ -0,0 +1,213 @@ +//===--- USRFinder.cpp - Clang refactoring library ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file Implements a recursive AST visitor that finds the USR of a symbol at a +/// point. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Refactoring/Rename/USRFinder.h" +#include "clang/AST/AST.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Index/USRGeneration.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/SmallVector.h" + +using namespace llvm; + +namespace clang { +namespace tooling { + +// NamedDeclFindingASTVisitor recursively visits each AST node to find the +// symbol underneath the cursor. +// FIXME: move to separate .h/.cc file if this gets too large. +namespace { +class NamedDeclFindingASTVisitor + : public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> { +public: + // \brief Finds the NamedDecl at a point in the source. + // \param Point the location in the source to search for the NamedDecl. + explicit NamedDeclFindingASTVisitor(const SourceLocation Point, + const ASTContext &Context) + : Result(nullptr), Point(Point), Context(Context) {} + + // \brief Finds the NamedDecl for a name in the source. + // \param Name the fully qualified name. + explicit NamedDeclFindingASTVisitor(const std::string &Name, + const ASTContext &Context) + : Result(nullptr), Name(Name), Context(Context) {} + + // Declaration visitors: + + // \brief Checks if the point falls within the NameDecl. This covers every + // declaration of a named entity that we may come across. Usually, just + // checking if the point lies within the length of the name of the declaration + // and the start location is sufficient. + bool VisitNamedDecl(const NamedDecl *Decl) { + return dyn_cast<CXXConversionDecl>(Decl) + ? true + : setResult(Decl, Decl->getLocation(), + Decl->getNameAsString().length()); + } + + // Expression visitors: + + bool VisitDeclRefExpr(const DeclRefExpr *Expr) { + const NamedDecl *Decl = Expr->getFoundDecl(); + return setResult(Decl, Expr->getLocation(), + Decl->getNameAsString().length()); + } + + bool VisitMemberExpr(const MemberExpr *Expr) { + const NamedDecl *Decl = Expr->getFoundDecl().getDecl(); + return setResult(Decl, Expr->getMemberLoc(), + Decl->getNameAsString().length()); + } + + // Other visitors: + + bool VisitTypeLoc(const TypeLoc Loc) { + const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); + const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken( + TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts()); + if (const auto *TemplateTypeParm = + dyn_cast<TemplateTypeParmType>(Loc.getType())) + return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc); + if (const auto *TemplateSpecType = + dyn_cast<TemplateSpecializationType>(Loc.getType())) { + return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(), + TypeBeginLoc, TypeEndLoc); + } + return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc, + TypeEndLoc); + } + + bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) { + for (const auto *Initializer : ConstructorDecl->inits()) { + // Ignore implicit initializers. + if (!Initializer->isWritten()) + continue; + if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) { + const SourceLocation InitBeginLoc = Initializer->getSourceLocation(), + InitEndLoc = Lexer::getLocForEndOfToken( + InitBeginLoc, 0, Context.getSourceManager(), + Context.getLangOpts()); + if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc)) + return false; + } + } + return true; + } + + // Other: + + const NamedDecl *getNamedDecl() { return Result; } + + // \brief Determines if a namespace qualifier contains the point. + // \returns false on success and sets Result. + void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) { + while (NameLoc) { + const NamespaceDecl *Decl = + NameLoc.getNestedNameSpecifier()->getAsNamespace(); + setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc()); + NameLoc = NameLoc.getPrefix(); + } + } + +private: + // \brief Sets Result to Decl if the Point is within Start and End. + // \returns false on success. + bool setResult(const NamedDecl *Decl, SourceLocation Start, + SourceLocation End) { + if (!Decl) + return true; + if (Name.empty()) { + // Offset is used to find the declaration. + if (!Start.isValid() || !Start.isFileID() || !End.isValid() || + !End.isFileID() || !isPointWithin(Start, End)) + return true; + } else { + // Fully qualified name is used to find the declaration. + if (Name != Decl->getQualifiedNameAsString() && + Name != "::" + Decl->getQualifiedNameAsString()) + return true; + } + Result = Decl; + return false; + } + + // \brief Sets Result to Decl if Point is within Loc and Loc + Offset. + // \returns false on success. + bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) { + // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc). + return Offset == 0 || + setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1)); + } + + // \brief Determines if the Point is within Start and End. + bool isPointWithin(const SourceLocation Start, const SourceLocation End) { + // FIXME: Add tests for Point == End. + return Point == Start || Point == End || + (Context.getSourceManager().isBeforeInTranslationUnit(Start, + Point) && + Context.getSourceManager().isBeforeInTranslationUnit(Point, End)); + } + + const NamedDecl *Result; + const SourceLocation Point; // The location to find the NamedDecl. + const std::string Name; + const ASTContext &Context; +}; +} // namespace + +const NamedDecl *getNamedDeclAt(const ASTContext &Context, + const SourceLocation Point) { + const SourceManager &SM = Context.getSourceManager(); + NamedDeclFindingASTVisitor Visitor(Point, Context); + + // Try to be clever about pruning down the number of top-level declarations we + // see. If both start and end is either before or after the point we're + // looking for the point cannot be inside of this decl. Don't even look at it. + for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) { + SourceLocation StartLoc = CurrDecl->getLocStart(); + SourceLocation EndLoc = CurrDecl->getLocEnd(); + if (StartLoc.isValid() && EndLoc.isValid() && + SM.isBeforeInTranslationUnit(StartLoc, Point) != + SM.isBeforeInTranslationUnit(EndLoc, Point)) + Visitor.TraverseDecl(CurrDecl); + } + + NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context)); + for (const auto &Location : Finder.getNestedNameSpecifierLocations()) + Visitor.handleNestedNameSpecifierLoc(Location); + + return Visitor.getNamedDecl(); +} + +const NamedDecl *getNamedDeclFor(const ASTContext &Context, + const std::string &Name) { + NamedDeclFindingASTVisitor Visitor(Name, Context); + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + + return Visitor.getNamedDecl(); +} + +std::string getUSRForDecl(const Decl *Decl) { + llvm::SmallVector<char, 128> Buff; + + // FIXME: Add test for the nullptr case. + if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff)) + return ""; + + return std::string(Buff.data(), Buff.size()); +} + +} // end namespace tooling +} // end namespace clang diff --git a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp new file mode 100644 index 000000000000..2769802ad2bc --- /dev/null +++ b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp @@ -0,0 +1,236 @@ +//===--- USRFindingAction.cpp - Clang refactoring library -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides an action to find USR for the symbol at <offset>, as well as +/// all additional USRs. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h" +#include "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/FileManager.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/Rename/USRFinder.h" +#include "clang/Tooling/Tooling.h" + +#include <algorithm> +#include <set> +#include <string> +#include <vector> + +using namespace llvm; + +namespace clang { +namespace tooling { + +namespace { +// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to +// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given +// Decl refers to class and adds USRs of all overridden methods if Decl refers +// to virtual method. +class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> { +public: + AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context) + : FoundDecl(FoundDecl), Context(Context) {} + + std::vector<std::string> Find() { + // Fill OverriddenMethods and PartialSpecs storages. + TraverseDecl(Context.getTranslationUnitDecl()); + if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) { + addUSRsOfOverridenFunctions(MethodDecl); + for (const auto &OverriddenMethod : OverriddenMethods) { + if (checkIfOverriddenFunctionAscends(OverriddenMethod)) + USRSet.insert(getUSRForDecl(OverriddenMethod)); + } + } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) { + handleCXXRecordDecl(RecordDecl); + } else if (const auto *TemplateDecl = + dyn_cast<ClassTemplateDecl>(FoundDecl)) { + handleClassTemplateDecl(TemplateDecl); + } else { + USRSet.insert(getUSRForDecl(FoundDecl)); + } + return std::vector<std::string>(USRSet.begin(), USRSet.end()); + } + + bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) { + if (MethodDecl->isVirtual()) + OverriddenMethods.push_back(MethodDecl); + return true; + } + + bool VisitClassTemplatePartialSpecializationDecl( + const ClassTemplatePartialSpecializationDecl *PartialSpec) { + PartialSpecs.push_back(PartialSpec); + return true; + } + +private: + void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) { + RecordDecl = RecordDecl->getDefinition(); + if (const auto *ClassTemplateSpecDecl = + dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl)) + handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate()); + addUSRsOfCtorDtors(RecordDecl); + } + + void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) { + for (const auto *Specialization : TemplateDecl->specializations()) + addUSRsOfCtorDtors(Specialization); + + for (const auto *PartialSpec : PartialSpecs) { + if (PartialSpec->getSpecializedTemplate() == TemplateDecl) + addUSRsOfCtorDtors(PartialSpec); + } + addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl()); + } + + void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) { + RecordDecl = RecordDecl->getDefinition(); + + // Skip if the CXXRecordDecl doesn't have definition. + if (!RecordDecl) + return; + + for (const auto *CtorDecl : RecordDecl->ctors()) + USRSet.insert(getUSRForDecl(CtorDecl)); + + USRSet.insert(getUSRForDecl(RecordDecl->getDestructor())); + USRSet.insert(getUSRForDecl(RecordDecl)); + } + + void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) { + USRSet.insert(getUSRForDecl(MethodDecl)); + // Recursively visit each OverridenMethod. + for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) + addUSRsOfOverridenFunctions(OverriddenMethod); + } + + bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) { + for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) { + if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end()) + return true; + return checkIfOverriddenFunctionAscends(OverriddenMethod); + } + return false; + } + + const Decl *FoundDecl; + ASTContext &Context; + std::set<std::string> USRSet; + std::vector<const CXXMethodDecl *> OverriddenMethods; + std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs; +}; +} // namespace + +class NamedDeclFindingConsumer : public ASTConsumer { +public: + NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets, + ArrayRef<std::string> QualifiedNames, + std::vector<std::string> &SpellingNames, + std::vector<std::vector<std::string>> &USRList, + bool Force, bool &ErrorOccurred) + : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames), + SpellingNames(SpellingNames), USRList(USRList), Force(Force), + ErrorOccurred(ErrorOccurred) {} + +private: + bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr, + unsigned SymbolOffset, const std::string &QualifiedName) { + DiagnosticsEngine &Engine = Context.getDiagnostics(); + const FileID MainFileID = SourceMgr.getMainFileID(); + + if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) { + ErrorOccurred = true; + unsigned InvalidOffset = Engine.getCustomDiagID( + DiagnosticsEngine::Error, + "SourceLocation in file %0 at offset %1 is invalid"); + Engine.Report(SourceLocation(), InvalidOffset) + << SourceMgr.getFileEntryForID(MainFileID)->getName() << SymbolOffset; + return false; + } + + const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID) + .getLocWithOffset(SymbolOffset); + const NamedDecl *FoundDecl = QualifiedName.empty() + ? getNamedDeclAt(Context, Point) + : getNamedDeclFor(Context, QualifiedName); + + if (FoundDecl == nullptr) { + if (QualifiedName.empty()) { + FullSourceLoc FullLoc(Point, SourceMgr); + unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID( + DiagnosticsEngine::Error, + "clang-rename could not find symbol (offset %0)"); + Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset; + ErrorOccurred = true; + return false; + } + + if (Force) + return true; + + unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID( + DiagnosticsEngine::Error, "clang-rename could not find symbol %0"); + Engine.Report(CouldNotFindSymbolNamed) << QualifiedName; + ErrorOccurred = true; + return false; + } + + // If FoundDecl is a constructor or destructor, we want to instead take + // the Decl of the corresponding class. + if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl)) + FoundDecl = CtorDecl->getParent(); + else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl)) + FoundDecl = DtorDecl->getParent(); + + SpellingNames.push_back(FoundDecl->getNameAsString()); + AdditionalUSRFinder Finder(FoundDecl, Context); + USRList.push_back(Finder.Find()); + return true; + } + + void HandleTranslationUnit(ASTContext &Context) override { + const SourceManager &SourceMgr = Context.getSourceManager(); + for (unsigned Offset : SymbolOffsets) { + if (!FindSymbol(Context, SourceMgr, Offset, "")) + return; + } + for (const std::string &QualifiedName : QualifiedNames) { + if (!FindSymbol(Context, SourceMgr, 0, QualifiedName)) + return; + } + } + + ArrayRef<unsigned> SymbolOffsets; + ArrayRef<std::string> QualifiedNames; + std::vector<std::string> &SpellingNames; + std::vector<std::vector<std::string>> &USRList; + bool Force; + bool &ErrorOccurred; +}; + +std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() { + return llvm::make_unique<NamedDeclFindingConsumer>( + SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force, + ErrorOccurred); +} + +} // end namespace tooling +} // end namespace clang diff --git a/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp new file mode 100644 index 000000000000..934507fe6eae --- /dev/null +++ b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp @@ -0,0 +1,509 @@ +//===--- USRLocFinder.cpp - Clang refactoring library ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Methods for finding all instances of a USR. Our strategy is very +/// simple; we just compare the USR at every relevant AST node with the one +/// provided. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Refactoring/Rename/USRLocFinder.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "clang/Tooling/Core/Lookup.h" +#include "clang/Tooling/Refactoring/Rename/USRFinder.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include <cstddef> +#include <set> +#include <string> +#include <vector> + +using namespace llvm; + +namespace clang { +namespace tooling { + +namespace { + +// \brief This visitor recursively searches for all instances of a USR in a +// translation unit and stores them for later usage. +class USRLocFindingASTVisitor + : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> { +public: + explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs, + StringRef PrevName, + const ASTContext &Context) + : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) { + } + + // Declaration visitors: + + bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) { + for (const auto *Initializer : ConstructorDecl->inits()) { + // Ignore implicit initializers. + if (!Initializer->isWritten()) + continue; + if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) { + if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end()) + LocationsFound.push_back(Initializer->getSourceLocation()); + } + } + return true; + } + + bool VisitNamedDecl(const NamedDecl *Decl) { + if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) + checkAndAddLocation(Decl->getLocation()); + return true; + } + + // Expression visitors: + + bool VisitDeclRefExpr(const DeclRefExpr *Expr) { + const NamedDecl *Decl = Expr->getFoundDecl(); + + if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) { + const SourceManager &Manager = Decl->getASTContext().getSourceManager(); + SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation()); + checkAndAddLocation(Location); + } + + return true; + } + + bool VisitMemberExpr(const MemberExpr *Expr) { + const NamedDecl *Decl = Expr->getFoundDecl().getDecl(); + if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) { + const SourceManager &Manager = Decl->getASTContext().getSourceManager(); + SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc()); + checkAndAddLocation(Location); + } + return true; + } + + // Other visitors: + + bool VisitTypeLoc(const TypeLoc Loc) { + if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) != + USRSet.end()) + checkAndAddLocation(Loc.getBeginLoc()); + if (const auto *TemplateTypeParm = + dyn_cast<TemplateTypeParmType>(Loc.getType())) { + if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) != + USRSet.end()) + checkAndAddLocation(Loc.getBeginLoc()); + } + return true; + } + + // Non-visitors: + + // \brief Returns a list of unique locations. Duplicate or overlapping + // locations are erroneous and should be reported! + const std::vector<clang::SourceLocation> &getLocationsFound() const { + return LocationsFound; + } + + // Namespace traversal: + void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) { + while (NameLoc) { + const NamespaceDecl *Decl = + NameLoc.getNestedNameSpecifier()->getAsNamespace(); + if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) + checkAndAddLocation(NameLoc.getLocalBeginLoc()); + NameLoc = NameLoc.getPrefix(); + } + } + +private: + void checkAndAddLocation(SourceLocation Loc) { + const SourceLocation BeginLoc = Loc; + const SourceLocation EndLoc = Lexer::getLocForEndOfToken( + BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts()); + StringRef TokenName = + Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc), + Context.getSourceManager(), Context.getLangOpts()); + size_t Offset = TokenName.find(PrevName); + + // The token of the source location we find actually has the old + // name. + if (Offset != StringRef::npos) + LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset)); + } + + const std::set<std::string> USRSet; + const std::string PrevName; + std::vector<clang::SourceLocation> LocationsFound; + const ASTContext &Context; +}; + +SourceLocation StartLocationForType(TypeLoc TL) { + // For elaborated types (e.g. `struct a::A`) we want the portion after the + // `struct` but including the namespace qualifier, `a::`. + if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) { + NestedNameSpecifierLoc NestedNameSpecifier = + ElaboratedTypeLoc.getQualifierLoc(); + if (NestedNameSpecifier.getNestedNameSpecifier()) + return NestedNameSpecifier.getBeginLoc(); + TL = TL.getNextTypeLoc(); + } + return TL.getLocStart(); +} + +SourceLocation EndLocationForType(TypeLoc TL) { + // Dig past any namespace or keyword qualifications. + while (TL.getTypeLocClass() == TypeLoc::Elaborated || + TL.getTypeLocClass() == TypeLoc::Qualified) + TL = TL.getNextTypeLoc(); + + // The location for template specializations (e.g. Foo<int>) includes the + // templated types in its location range. We want to restrict this to just + // before the `<` character. + if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) { + return TL.castAs<TemplateSpecializationTypeLoc>() + .getLAngleLoc() + .getLocWithOffset(-1); + } + return TL.getEndLoc(); +} + +NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) { + // Dig past any keyword qualifications. + while (TL.getTypeLocClass() == TypeLoc::Qualified) + TL = TL.getNextTypeLoc(); + + // For elaborated types (e.g. `struct a::A`) we want the portion after the + // `struct` but including the namespace qualifier, `a::`. + if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) + return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier(); + return nullptr; +} + +// Find all locations identified by the given USRs for rename. +// +// This class will traverse the AST and find every AST node whose USR is in the +// given USRs' set. +class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> { +public: + RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context) + : USRSet(USRs.begin(), USRs.end()), Context(Context) {} + + // A structure records all information of a symbol reference being renamed. + // We try to add as few prefix qualifiers as possible. + struct RenameInfo { + // The begin location of a symbol being renamed. + SourceLocation Begin; + // The end location of a symbol being renamed. + SourceLocation End; + // The declaration of a symbol being renamed (can be nullptr). + const NamedDecl *FromDecl; + // The declaration in which the nested name is contained (can be nullptr). + const Decl *Context; + // The nested name being replaced (can be nullptr). + const NestedNameSpecifier *Specifier; + }; + + // FIXME: Currently, prefix qualifiers will be added to the renamed symbol + // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming + // "a::Foo" to "b::Bar"). + // For renaming declarations/definitions, prefix qualifiers should be filtered + // out. + bool VisitNamedDecl(const NamedDecl *Decl) { + // UsingDecl has been handled in other place. + if (llvm::isa<UsingDecl>(Decl)) + return true; + + // DestructorDecl has been handled in Typeloc. + if (llvm::isa<CXXDestructorDecl>(Decl)) + return true; + + if (Decl->isImplicit()) + return true; + + if (isInUSRSet(Decl)) { + RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr, + nullptr, nullptr}; + RenameInfos.push_back(Info); + } + return true; + } + + bool VisitDeclRefExpr(const DeclRefExpr *Expr) { + const NamedDecl *Decl = Expr->getFoundDecl(); + if (isInUSRSet(Decl)) { + RenameInfo Info = {Expr->getSourceRange().getBegin(), + Expr->getSourceRange().getEnd(), Decl, + getClosestAncestorDecl(*Expr), Expr->getQualifier()}; + RenameInfos.push_back(Info); + } + + return true; + } + + bool VisitUsingDecl(const UsingDecl *Using) { + for (const auto *UsingShadow : Using->shadows()) { + if (isInUSRSet(UsingShadow->getTargetDecl())) { + UsingDecls.push_back(Using); + break; + } + } + return true; + } + + bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) { + if (!NestedLoc.getNestedNameSpecifier()->getAsType()) + return true; + if (IsTypeAliasWhichWillBeRenamedElsewhere(NestedLoc.getTypeLoc())) + return true; + + if (const auto *TargetDecl = + getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) { + if (isInUSRSet(TargetDecl)) { + RenameInfo Info = {NestedLoc.getBeginLoc(), + EndLocationForType(NestedLoc.getTypeLoc()), + TargetDecl, getClosestAncestorDecl(NestedLoc), + NestedLoc.getNestedNameSpecifier()->getPrefix()}; + RenameInfos.push_back(Info); + } + } + return true; + } + + bool VisitTypeLoc(TypeLoc Loc) { + if (IsTypeAliasWhichWillBeRenamedElsewhere(Loc)) + return true; + + auto Parents = Context.getParents(Loc); + TypeLoc ParentTypeLoc; + if (!Parents.empty()) { + // Handle cases of nested name specificier locations. + // + // The VisitNestedNameSpecifierLoc interface is not impelmented in + // RecursiveASTVisitor, we have to handle it explicitly. + if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) { + VisitNestedNameSpecifierLocations(*NSL); + return true; + } + + if (const auto *TL = Parents[0].get<TypeLoc>()) + ParentTypeLoc = *TL; + } + + // Handle the outermost TypeLoc which is directly linked to the interesting + // declaration and don't handle nested name specifier locations. + if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) { + if (isInUSRSet(TargetDecl)) { + // Only handle the outermost typeLoc. + // + // For a type like "a::Foo", there will be two typeLocs for it. + // One ElaboratedType, the other is RecordType: + // + // ElaboratedType 0x33b9390 'a::Foo' sugar + // `-RecordType 0x338fef0 'class a::Foo' + // `-CXXRecord 0x338fe58 'Foo' + // + // Skip if this is an inner typeLoc. + if (!ParentTypeLoc.isNull() && + isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc))) + return true; + RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc), + TargetDecl, getClosestAncestorDecl(Loc), + GetNestedNameForType(Loc)}; + RenameInfos.push_back(Info); + return true; + } + } + + // Handle specific template class specialiation cases. + if (const auto *TemplateSpecType = + dyn_cast<TemplateSpecializationType>(Loc.getType())) { + TypeLoc TargetLoc = Loc; + if (!ParentTypeLoc.isNull()) { + if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType())) + TargetLoc = ParentTypeLoc; + } + + if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) { + TypeLoc TargetLoc = Loc; + // FIXME: Find a better way to handle this case. + // For the qualified template class specification type like + // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc + // (ElaboratedType) of the TemplateSpecializationType in order to + // catch the prefix qualifiers "ns::". + if (!ParentTypeLoc.isNull() && + llvm::isa<ElaboratedType>(ParentTypeLoc.getType())) + TargetLoc = ParentTypeLoc; + RenameInfo Info = { + StartLocationForType(TargetLoc), EndLocationForType(TargetLoc), + TemplateSpecType->getTemplateName().getAsTemplateDecl(), + getClosestAncestorDecl( + ast_type_traits::DynTypedNode::create(TargetLoc)), + GetNestedNameForType(TargetLoc)}; + RenameInfos.push_back(Info); + } + } + return true; + } + + // Returns a list of RenameInfo. + const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; } + + // Returns a list of using declarations which are needed to update. + const std::vector<const UsingDecl *> &getUsingDecls() const { + return UsingDecls; + } + +private: + // FIXME: This method may not be suitable for renaming other types like alias + // types. Need to figure out a way to handle it. + bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const { + while (!TL.isNull()) { + // SubstTemplateTypeParm is the TypeLocation class for a substituted type + // inside a template expansion so we ignore these. For example: + // + // template<typename T> struct S { + // T t; // <-- this T becomes a TypeLoc(int) with class + // // SubstTemplateTypeParm when S<int> is instantiated + // } + if (TL.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm) + return true; + + // Typedef is the TypeLocation class for a type which is a typedef to the + // type we want to replace. We ignore the use of the typedef as we will + // replace the definition of it. For example: + // + // typedef int T; + // T a; // <--- This T is a TypeLoc(int) with class Typedef. + if (TL.getTypeLocClass() == TypeLoc::Typedef) + return true; + TL = TL.getNextTypeLoc(); + } + return false; + } + + // Get the supported declaration from a given typeLoc. If the declaration type + // is not supported, returns nullptr. + // + // FIXME: support more types, e.g. enum, type alias. + const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) { + if (const auto *RD = Loc.getType()->getAsCXXRecordDecl()) + return RD; + return nullptr; + } + + // Get the closest ancester which is a declaration of a given AST node. + template <typename ASTNodeType> + const Decl *getClosestAncestorDecl(const ASTNodeType &Node) { + auto Parents = Context.getParents(Node); + // FIXME: figure out how to handle it when there are multiple parents. + if (Parents.size() != 1) + return nullptr; + if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf( + Parents[0].getNodeKind())) + return Parents[0].template get<Decl>(); + return getClosestAncestorDecl(Parents[0]); + } + + // Get the parent typeLoc of a given typeLoc. If there is no such parent, + // return nullptr. + const TypeLoc *getParentTypeLoc(TypeLoc Loc) const { + auto Parents = Context.getParents(Loc); + // FIXME: figure out how to handle it when there are multiple parents. + if (Parents.size() != 1) + return nullptr; + return Parents[0].get<TypeLoc>(); + } + + // Check whether the USR of a given Decl is in the USRSet. + bool isInUSRSet(const Decl *Decl) const { + auto USR = getUSRForDecl(Decl); + if (USR.empty()) + return false; + return llvm::is_contained(USRSet, USR); + } + + const std::set<std::string> USRSet; + ASTContext &Context; + std::vector<RenameInfo> RenameInfos; + // Record all interested using declarations which contains the using-shadow + // declarations of the symbol declarations being renamed. + std::vector<const UsingDecl *> UsingDecls; +}; + +} // namespace + +std::vector<SourceLocation> +getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName, + Decl *Decl) { + USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext()); + Visitor.TraverseDecl(Decl); + NestedNameSpecifierLocFinder Finder(Decl->getASTContext()); + + for (const auto &Location : Finder.getNestedNameSpecifierLocations()) + Visitor.handleNestedNameSpecifierLoc(Location); + + return Visitor.getLocationsFound(); +} + +std::vector<tooling::AtomicChange> +createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs, + llvm::StringRef NewName, Decl *TranslationUnitDecl) { + RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext()); + Finder.TraverseDecl(TranslationUnitDecl); + + const SourceManager &SM = + TranslationUnitDecl->getASTContext().getSourceManager(); + + std::vector<tooling::AtomicChange> AtomicChanges; + auto Replace = [&](SourceLocation Start, SourceLocation End, + llvm::StringRef Text) { + tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start); + llvm::Error Err = ReplaceChange.replace( + SM, CharSourceRange::getTokenRange(Start, End), Text); + if (Err) { + llvm::errs() << "Faile to add replacement to AtomicChange: " + << llvm::toString(std::move(Err)) << "\n"; + return; + } + AtomicChanges.push_back(std::move(ReplaceChange)); + }; + + for (const auto &RenameInfo : Finder.getRenameInfos()) { + std::string ReplacedName = NewName.str(); + if (RenameInfo.FromDecl && RenameInfo.Context) { + if (!llvm::isa<clang::TranslationUnitDecl>( + RenameInfo.Context->getDeclContext())) { + ReplacedName = tooling::replaceNestedName( + RenameInfo.Specifier, RenameInfo.Context->getDeclContext(), + RenameInfo.FromDecl, + NewName.startswith("::") ? NewName.str() : ("::" + NewName).str()); + } + } + // If the NewName contains leading "::", add it back. + if (NewName.startswith("::") && NewName.substr(2) == ReplacedName) + ReplacedName = NewName.str(); + Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName); + } + + // Hanlde using declarations explicitly as "using a::Foo" don't trigger + // typeLoc for "a::Foo". + for (const auto *Using : Finder.getUsingDecls()) + Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str()); + + return AtomicChanges; +} + +} // end namespace tooling +} // end namespace clang diff --git a/test/Analysis/malloc-overflow2.c b/test/Analysis/malloc-overflow2.c index 2e1b1d4d2b24..7c580602e682 100644 --- a/test/Analysis/malloc-overflow2.c +++ b/test/Analysis/malloc-overflow2.c @@ -1,4 +1,5 @@ // RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -analyzer-checker=alpha.security.MallocOverflow,unix -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -analyzer-checker=alpha.security.MallocOverflow,unix,optin.portability -DPORTABILITY -verify %s typedef __typeof__(sizeof(int)) size_t; extern void *malloc(size_t); @@ -32,5 +33,8 @@ static int table_build_1(struct table *t) { } void *f(int n) { - return malloc(n * 0 * sizeof(int)); // expected-warning {{Call to 'malloc' has an allocation size of 0 bytes}} + return malloc(n * 0 * sizeof(int)); +#ifdef PORTABILITY + // expected-warning@-2{{Call to 'malloc' has an allocation size of 0 bytes}} +#endif } diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c index 3eccd51d2c60..481f545e28bc 100644 --- a/test/Analysis/unix-fns.c +++ b/test/Analysis/unix-fns.c @@ -1,7 +1,7 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist // RUN: FileCheck --input-file=%t.plist %s // RUN: mkdir -p %t.dir -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s // RUN: rm -fR %t.dir struct _opaque_pthread_once_t { long __sig; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 23d23bcddcc1..fa926c584f8e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -47,6 +47,7 @@ list(APPEND CLANG_TEST_DEPS clang-tblgen clang-offload-bundler clang-import-test + clang-rename ) if(CLANG_ENABLE_STATIC_ANALYZER) diff --git a/test/CodeGen/arm-execute-only.c b/test/CodeGen/arm-execute-only.c new file mode 100644 index 000000000000..6d88ff611d68 --- /dev/null +++ b/test/CodeGen/arm-execute-only.c @@ -0,0 +1,78 @@ +// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv6t2-eabi -### -mexecute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv6t2-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv7m-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv7m-eabi -### -mexecute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv7m-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.base-eabi -### -mexecute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv8m.base-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.main-eabi -### -mexecute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv8m.main-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + + +// -mpure-code flag for GCC compatibility +// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv6t2-eabi -### -mpure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv6t2-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv7m-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv7m-eabi -### -mpure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv7m-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.base-eabi -### -mpure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv8m.base-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target armv8m.main-eabi -### -mpure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target armv8m.main-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// CHECK-NO-EXECUTE-ONLY-NOT: "+execute-only" +// CHECK-EXECUTE-ONLY: "+execute-only" + +void a() {} diff --git a/test/CodeGen/arm-v8.1a-neon-intrinsics.c b/test/CodeGen/arm-v8.1a-neon-intrinsics.c index 788883100456..6f5867b6c11f 100644 --- a/test/CodeGen/arm-v8.1a-neon-intrinsics.c +++ b/test/CodeGen/arm-v8.1a-neon-intrinsics.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple armv8.1a-linux-gnu -target-feature +neon \ +// RUN: %clang_cc1 -triple armv8.1a-linux-gnu -target-abi apcs-gnu -target-feature +neon \ // RUN: -S -emit-llvm -o - %s \ // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index c66d83611ed1..c3356461a348 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror | FileCheck %s + +// FIXME: It's wrong to check LLVM IR transformations from clang. This run should be removed and tests added to the appropriate LLVM pass. + // RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -O2 -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=O2 #include <immintrin.h> @@ -8240,10 +8243,10 @@ __m128 test_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // O2-LABEL: @test_mm_mask_move_ss // O2: %[[M:.*]] = and i8 %__U, 1 - // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0 - // O2: %[[ELM1:.*]] = extractelement <4 x float> %__B, i32 0 - // O2: %[[ELM2:.*]] = extractelement <4 x float> %__W, i32 0 - // O2: %[[SEL:.*]] = select i1 %[[M2]], float %[[ELM1]], float %[[ELM2]] + // O2: %[[M2:.*]] = icmp + // O2: %[[ELM1:.*]] = extractelement <4 x float> + // O2: %[[ELM2:.*]] = extractelement <4 x float> + // O2: %[[SEL:.*]] = select i1 %[[M2]] // O2: %[[RES:.*]] = insertelement <4 x float> %__A, float %[[SEL]], i32 0 // O2: ret <4 x float> %[[RES]] return _mm_mask_move_ss ( __W, __U, __A, __B); @@ -8253,9 +8256,9 @@ __m128 test_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) { // O2-LABEL: @test_mm_maskz_move_ss // O2: %[[M:.*]] = and i8 %__U, 1 - // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0 + // O2: %[[M2:.*]] = icmp // O2: %[[ELM1:.*]] = extractelement <4 x float> %__B, i32 0 - // O2: %[[SEL:.*]] = select i1 %[[M2]], float %[[ELM1]], float 0.0 + // O2: %[[SEL:.*]] = select i1 %[[M2]] // O2: %[[RES:.*]] = insertelement <4 x float> %__A, float %[[SEL]], i32 0 // O2: ret <4 x float> %[[RES]] return _mm_maskz_move_ss (__U, __A, __B); @@ -8265,10 +8268,10 @@ __m128d test_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __ { // O2-LABEL: @test_mm_mask_move_sd // O2: %[[M:.*]] = and i8 %__U, 1 - // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0 - // O2: %[[ELM1:.*]] = extractelement <2 x double> %__B, i32 0 - // O2: %[[ELM2:.*]] = extractelement <2 x double> %__W, i32 0 - // O2: %[[SEL:.*]] = select i1 %[[M2]], double %[[ELM1]], double %[[ELM2]] + // O2: %[[M2:.*]] = icmp + // O2: %[[ELM1:.*]] = extractelement <2 x double> + // O2: %[[ELM2:.*]] = extractelement <2 x double> + // O2: %[[SEL:.*]] = select i1 %[[M2]] // O2: %[[RES:.*]] = insertelement <2 x double> %__A, double %[[SEL]], i32 0 // O2: ret <2 x double> %[[RES]] return _mm_mask_move_sd ( __W, __U, __A, __B); @@ -8278,9 +8281,9 @@ __m128d test_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) { // O2-LABEL: @test_mm_maskz_move_sd // O2: %[[M:.*]] = and i8 %__U, 1 - // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0 + // O2: %[[M2:.*]] = icmp // O2: %[[ELM1:.*]] = extractelement <2 x double> %__B, i32 0 - // O2: %[[SEL:.*]] = select i1 %[[M2]], double %[[ELM1]], double 0.0 + // O2: %[[SEL:.*]] = select i1 %[[M2]] // O2: %[[RES:.*]] = insertelement <2 x double> %__A, double %[[SEL]], i32 0 // O2: ret <2 x double> %[[RES]] return _mm_maskz_move_sd (__U, __A, __B); diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c index 0c0b87945d42..e0f72d2e5034 100644 --- a/test/CodeGen/builtins-wasm.c +++ b/test/CodeGen/builtins-wasm.c @@ -14,3 +14,15 @@ __SIZE_TYPE__ f2(__SIZE_TYPE__ delta) { // WEBASSEMBLY32: call i32 @llvm.wasm.grow.memory.i32(i32 %{{.*}}) // WEBASSEMBLY64: call i64 @llvm.wasm.grow.memory.i64(i64 %{{.*}}) } + +void f3(unsigned int tag, void *obj) { + return __builtin_wasm_throw(tag, obj); +// WEBASSEMBLY32: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}}) +// WEBASSEMBLY64: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}}) +} + +void f4() { + return __builtin_wasm_rethrow(); +// WEBASSEMBLY32: call void @llvm.wasm.rethrow() +// WEBASSEMBLY64: call void @llvm.wasm.rethrow() +} diff --git a/test/CodeGen/lto-newpm-pipeline.c b/test/CodeGen/lto-newpm-pipeline.c new file mode 100644 index 000000000000..10112da6d508 --- /dev/null +++ b/test/CodeGen/lto-newpm-pipeline.c @@ -0,0 +1,53 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O0 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-O0 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O0 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-O0 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O1 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O1 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O2 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O2 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -O3 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -O3 %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -Os %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -Os %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=full -Oz %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-FULL-OPTIMIZED +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -flto=thin -Oz %s 2>&1 | FileCheck %s \ +// RUN: -check-prefix=CHECK-THIN-OPTIMIZED + +// CHECK-FULL-O0: Starting llvm::Module pass manager run. +// CHECK-FULL-O0: Running pass: AlwaysInlinerPass +// CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass +// CHECK-FULL-O0: Finished llvm::Module pass manager run. + +// CHECK-THIN-O0: Starting llvm::Module pass manager run. +// CHECK-THIN-O0: Running pass: AlwaysInlinerPass +// CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass +// CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass +// CHECK-THIN-O0: Finished llvm::Module pass manager run. + +// TODO: The LTO pre-link pipeline currently invokes +// buildPerModuleDefaultPipeline(), which contains LoopVectorizePass. +// This may change as the pipeline gets implemented. +// CHECK-FULL-OPTIMIZED: Starting llvm::Function pass manager run. +// CHECK-FULL-OPTIMIZED: Running pass: LoopVectorizePass +// CHECK-FULL-OPTIMIZED: Running pass: BitcodeWriterPass + +// The ThinLTO pre-link pipeline shouldn't contain passes like +// LoopVectorizePass. +// CHECK-THIN-OPTIMIZED: Starting llvm::Function pass manager run. +// CHECK-THIN-OPTIMIZED-NOT: Running pass: LoopVectorizePass +// CHECK-THIN-OPTIMIZED: Running pass: NameAnonGlobalPass +// CHECK-THIN-OPTIMIZED: Running pass: ThinLTOBitcodeWriterPass + +void Foo() {} diff --git a/test/CodeGen/mangle-ms.c b/test/CodeGen/mangle-ms.c index 0ad43d5e06c2..042c72e6d794 100644 --- a/test/CodeGen/mangle-ms.c +++ b/test/CodeGen/mangle-ms.c @@ -2,3 +2,12 @@ // CHECK: define void @"\01?f@@$$J0YAXP6AX@Z@Z" __attribute__((overloadable)) void f(void (*x)()) {} + +// CHECK: define void @f +void f(void (*x)(int)) {} + +// CHECK: define void @g +void g(void (*x)(int)) {} + +// CHECK: define void @"\01?g@@$$J0YAXP6AX@Z@Z" +__attribute__((overloadable)) void g(void (*x)()) {} diff --git a/test/CodeGen/mangle.c b/test/CodeGen/mangle.c index 46ef512f6950..f94139bc5e3c 100644 --- a/test/CodeGen/mangle.c +++ b/test/CodeGen/mangle.c @@ -9,6 +9,10 @@ void __attribute__((__overloadable__)) f0(int a) {} // CHECK: @_Z2f0l void __attribute__((__overloadable__)) f0(long b) {} +// Unless it's unmarked. +// CHECK: @f0 +void f0(float b) {} + // CHECK: @bar // These should get merged. diff --git a/test/CodeGen/named_reg_global.c b/test/CodeGen/named_reg_global.c index 1da625746891..232b74de1cab 100644 --- a/test/CodeGen/named_reg_global.c +++ b/test/CodeGen/named_reg_global.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86-64 // RUN: %clang_cc1 -triple arm64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM -// RUN: %clang_cc1 -triple armv7-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM +// RUN: %clang_cc1 -triple armv7-linux-gnu -target-abi apcs-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM // CHECK-NOT: @sp = common global diff --git a/test/CodeGen/neon-immediate-ubsan.c b/test/CodeGen/neon-immediate-ubsan.c index c3e1ce23301d..aacf76a6338b 100644 --- a/test/CodeGen/neon-immediate-ubsan.c +++ b/test/CodeGen/neon-immediate-ubsan.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple armv7s-linux-gnu -emit-llvm -o - %s \ +// RUN: %clang_cc1 -triple armv7s-linux-gnu -target-abi apcs-gnu -emit-llvm -o - %s \ // RUN: -target-feature +neon -target-cpu cortex-a8 \ // RUN: -fsanitize=signed-integer-overflow \ // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ARMV7 diff --git a/test/CodeGen/pgo-sample-thinlto-summary.c b/test/CodeGen/pgo-sample-thinlto-summary.c index 7782aeb76616..51c8faa6be6d 100644 --- a/test/CodeGen/pgo-sample-thinlto-summary.c +++ b/test/CodeGen/pgo-sample-thinlto-summary.c @@ -1,5 +1,9 @@ -// RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=O2 +// RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=SAMPLEPGO // RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -flto=thin -o - 2>&1 | FileCheck %s -check-prefix=THINLTO +// RUN: %clang_cc1 -O2 -fexperimental-new-pass-manager -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=SAMPLEPGO +// FIXME: Run the following command once LTOPreLinkDefaultPipeline is +// customized. +// %clang_cc1 -O2 -fexperimental-new-pass-manager -fprofile-sample-use=%S/Inputs/pgo-sample-thinlto-summary.prof %s -emit-llvm -flto=thin -o - 2>&1 | FileCheck %s -check-prefix=THINLTO // Checks if hot call is inlined by normal compile, but not inlined by // thinlto compile. @@ -11,9 +15,9 @@ void foo(int n) { g += baz(i); } -// O2-LABEL: define void @bar +// SAMPLEPGO-LABEL: define void @bar // THINLTO-LABEL: define void @bar -// O2-NOT: call{{.*}}foo +// SAMPLEPGO-NOT: call{{.*}}foo // THINLTO: call{{.*}}foo void bar(int n) { for (int i = 0; i < n; i++) @@ -21,10 +25,10 @@ void bar(int n) { } // Checks if loop unroll is invoked by normal compile, but not thinlto compile. -// O2-LABEL: define void @unroll +// SAMPLEPGO-LABEL: define void @unroll // THINLTO-LABEL: define void @unroll -// O2: call{{.*}}baz -// O2: call{{.*}}baz +// SAMPLEPGO: call{{.*}}baz +// SAMPLEPGO: call{{.*}}baz // THINLTO: call{{.*}}baz // THINLTO-NOT: call{{.*}}baz void unroll() { @@ -32,11 +36,13 @@ void unroll() { baz(i); } -// Check that icp is not invoked (both -O2 and ThinLTO). -// O2-LABEL: define void @icp +// Checks that icp is not invoked for ThinLTO, but invoked for normal samplepgo. +// SAMPLEPGO-LABEL: define void @icp // THINLTO-LABEL: define void @icp -// O2-NOT: if.true.direct_targ -// ThinLTO-NOT: if.true.direct_targ +// SAMPLEPGO: if.true.direct_targ +// FIXME: the following condition needs to be reversed once +// LTOPreLinkDefaultPipeline is customized. +// THINLTO-NOT: if.true.direct_targ void icp(void (*p)()) { p(); } diff --git a/test/CodeGen/xray-attributes-supported.cpp b/test/CodeGen/xray-attributes-supported.cpp index 860efb276f69..21a5dde53a05 100644 --- a/test/CodeGen/xray-attributes-supported.cpp +++ b/test/CodeGen/xray-attributes-supported.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple x86_64-unknown-linux-gnu | FileCheck %s -// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple arm-unknown-linux-gnu | FileCheck %s +// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple arm-unknown-linux-gnu -target-abi apcs-gnu | FileCheck %s // RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips-unknown-linux-gnu | FileCheck %s // RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mipsel-unknown-linux-gnu | FileCheck %s // RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips64-unknown-linux-gnu | FileCheck %s diff --git a/test/CodeGenCXX/dllexport-dtor-thunks.cpp b/test/CodeGenCXX/dllexport-dtor-thunks.cpp new file mode 100644 index 000000000000..52f9901620fa --- /dev/null +++ b/test/CodeGenCXX/dllexport-dtor-thunks.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -mconstructor-aliases -fms-extensions %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s + +struct __declspec(dllexport) A { virtual ~A(); }; +struct __declspec(dllexport) B { virtual ~B(); }; +struct __declspec(dllexport) C : A, B { virtual ~C(); }; +C::~C() {} + +// This thunk should *not* be dllexport. +// CHECK: define linkonce_odr i8* @"\01??_EC@@W7EAAPEAXI@Z" +// CHECK: define dllexport void @"\01??1C@@UEAA@XZ" diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index ee0f50e5e2d3..7e2f17f27a96 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -399,6 +399,13 @@ template void fn_tmpl<extern_c_func>(); extern "C" void __attribute__((overloadable)) overloaded_fn() {} // CHECK-DAG: @"\01?overloaded_fn@@$$J0YAXXZ" +extern "C" void overloaded_fn2() {} +// CHECK-DAG: @overloaded_fn2 +// +extern "C" void __attribute__((overloadable)) overloaded_fn3(); +extern "C" void overloaded_fn3() {} +// CHECK-DAG: @overloaded_fn3 + namespace UnnamedType { struct S { typedef struct {} *T1[1]; diff --git a/test/CodeGenCXX/msabi-blocks.cpp b/test/CodeGenCXX/msabi-blocks.cpp new file mode 100644 index 000000000000..bee59d9ed535 --- /dev/null +++ b/test/CodeGenCXX/msabi-blocks.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-X86 +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-X64 + +extern int e(void); + +void (^b)() = ^{ + static int i = 0; +}; + +// CHECK-X86-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0 + +void f(void) { + static int i = 0; + ^{ static int i = e(); }(); + +// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0 + + ^{ static int i = e(); }(); + +// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0 + + ^{ ^{ static int i = e(); }(); }(); + +// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0 +} + + +template <typename> +void g(void) { + ^{ static int i = e(); }(); +} + +template void g<char>(void); + +// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0 + +template void g<int>(void); + +// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0 + +inline void h(void) { + ^{ static int i = e(); }(); +} + +// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0 + +struct s { + int i = ^{ static int i = e(); return ++i; }(); + +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0 + + int j = ^{ static int i = e(); return ++i; }(); + +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0 + + void m(int i = ^{ static int i = e(); return ++i; }(), + int j = ^{ static int i = e(); return ++i; }()) {} + +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0 + + void n(int = ^{ static int i = e(); return ++i; }(), + int = ^{ static int i = e(); return ++i; }()) {} + +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0 + +}; + +struct t { + struct u { + int i = ^{ static int i = e(); return ++i; }(); + +// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0 +// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0 + + }; +}; + +void j(void) { + h(); + struct s s; + s.m(); + s.n(); + struct t::u t; +} + +#if 0 +template <typename T> +struct v { + static T i; +}; + +template <typename T> +T v<T>::i = ^{ static T i = T(); return i; }(); + +template class v<char>; +template class v<int>; +#endif + diff --git a/test/CodeGenObjC/ivar-type-encoding.m b/test/CodeGenObjC/ivar-type-encoding.m index ffa5e0d7af0d..2fd962cf07bb 100644 --- a/test/CodeGenObjC/ivar-type-encoding.m +++ b/test/CodeGenObjC/ivar-type-encoding.m @@ -33,3 +33,19 @@ int main() { // CHECK: @1 = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00" // CHECK: @2 = private unnamed_addr constant [9 x i8] c"_intIvar\00" // CHECK: @3 = private unnamed_addr constant [2 x i8] c"i\00" + +@interface Class1 { + int : 3; + short : 2; + long long ll; + char : 1; +} +@end + +@implementation Class1 +@end + +// CHECK: @{{.*}} = private unnamed_addr constant [5 x i8] c"b0i3\00" +// CHECK: @{{.*}} = private unnamed_addr constant [5 x i8] c"b3s2\00" +// CHECK: @{{.*}} = private unnamed_addr constant [2 x i8] c"q\00" +// CHECK: @{{.*}} = private unnamed_addr constant [{{7|6}} x i8] c"b{{128|96}}c1\00" diff --git a/test/CodeGenObjC/parameterized_classes.m b/test/CodeGenObjC/parameterized_classes.m index 8fe5c52b8d39..34aca35af313 100644 --- a/test/CodeGenObjC/parameterized_classes.m +++ b/test/CodeGenObjC/parameterized_classes.m @@ -96,3 +96,31 @@ void blockTest(NSMutableArray<void (^)(void)> *array, NSString *name) { _destination = a; } @end + +// CHECK-LABEL: define internal void @"\01-[C0 foo1]"( +// CHECK: {{.*}} = alloca +// CHECK: {{.*}} = alloca +// CHECK: %[[D:.*]] = alloca %[[TY:.*]]* +// CHECK: %[[TEMP:.*]] = alloca %[[TY]]* +// CHECK: %[[V4:.*]] = load %[[TY]]*, %[[TY]]** %[[D]] +// CHECK: store %[[TY]]* %[[V4]], %[[TY]]** %[[TEMP]] +// CHECK: %[[V7:.*]] = bitcast %[[TY]]** %[[TEMP]] to i8** +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8**)*)(i8* %{{.*}}, i8* %{{.*}}, i8** %[[V7]]) + +@interface P0<ObjectType> : NSObject +- (void)m0:(ObjectType *)first; +@end + +@interface C0 : NSObject +-(void)foo1; +@end + +@implementation C0 { + P0<NSString *> *x; +} + +-(void)foo1 { + NSString *d; + [x m0:&d]; +} +@end diff --git a/test/CodeGenObjC/protocol-comdat.m b/test/CodeGenObjC/protocol-comdat.m index 65e1b9fa2c82..a19ba8cf35dc 100644 --- a/test/CodeGenObjC/protocol-comdat.m +++ b/test/CodeGenObjC/protocol-comdat.m @@ -4,6 +4,9 @@ - (void) method; @end +@protocol Q; +@protocol R; + @interface I<P> @end @@ -11,9 +14,14 @@ - (void) method { } @end +_Bool f(void) { + return @protocol(Q) == @protocol(R); +} // CHECK: $"\01l_OBJC_PROTOCOL_$_P" = comdat any // CHECK: $"\01l_OBJC_LABEL_PROTOCOL_$_P" = comdat any +// CHECK: $"\01l_OBJC_PROTOCOL_REFERENCE_$_Q" = comdat any +// CHECK: $"\01l_OBJC_PROTOCOL_REFERENCE_$_R" = comdat any // CHECK: @"\01l_OBJC_PROTOCOL_$_P" = {{.*}}, comdat // CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, comdat diff --git a/test/CodeGenObjC/stret-1.m b/test/CodeGenObjC/stret-1.m index a7bcdda48b14..2314d5a9ecf5 100644 --- a/test/CodeGenObjC/stret-1.m +++ b/test/CodeGenObjC/stret-1.m @@ -12,11 +12,20 @@ struct stret one = {{1}}; int main(int argc, const char **argv) { - [(id)(argc&~255) method]; + struct stret s; + s = [(id)(argc&~255) method]; // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T0:%[^,]+]] // CHECK: [[T0P:%.*]] = bitcast %struct.stret* [[T0]] to i8* // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0P]], i8 0, i64 400, i32 4, i1 false) + s = [Test method]; + // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]] + // CHECK-NOT: call void @llvm.memset.p0i8.i64( + + [(id)(argc&~255) method]; + // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]] + // CHECK-NOT: call void @llvm.memset.p0i8.i64( + [Test method]; // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret [[T1:%[^,]+]] // CHECK-NOT: call void @llvm.memset.p0i8.i64( diff --git a/test/CodeGenObjC/stret-lifetime.m b/test/CodeGenObjC/stret-lifetime.m new file mode 100644 index 000000000000..d81ef34aeed4 --- /dev/null +++ b/test/CodeGenObjC/stret-lifetime.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple arm64-apple-darwin -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-darwin -fobjc-arc -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,ARC +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,ARC + +struct stret { int x[100]; }; +struct stret one = {{1}}; + +@interface Test ++(struct stret) method; ++(struct stret) methodConsuming:(id __attribute__((ns_consumed)))consumed; +@end + +void foo(id o, id p) { + [o method]; + // CHECK: @llvm.lifetime.start + // CHECK: call void bitcast {{.*}} @objc_msgSend + // CHECK: @llvm.lifetime.end + // CHECK-NOT: call void @llvm.memset + + [o methodConsuming:p]; + // ARC: [[T0:%.*]] = icmp eq i8* + // ARC: br i1 [[T0]] + + // CHECK: @llvm.lifetime.start + // CHECK: call void bitcast {{.*}} @objc_msgSend + // CHECK: @llvm.lifetime.end + // ARC: br label + + // ARC: call void @objc_release + // ARC: br label + + // CHECK-NOT: call void @llvm.memset +} diff --git a/test/CodeGenObjCXX/arc-indirect.mm b/test/CodeGenObjCXX/arc-indirect.mm new file mode 100644 index 000000000000..6982bac04118 --- /dev/null +++ b/test/CodeGenObjCXX/arc-indirect.mm @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -triple i686-unknown-windows-msvc -fobjc-runtime=gnustep -fobjc-arc -Wno-objc-root-class -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,CHECK-GNUSTEP %s +// RUN: %clang_cc1 -std=c++11 -triple i686-unknown-windows-msvc -fobjc-runtime=macosx -fobjc-arc -Wno-objc-root-class -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,CHECK-DARWIN %s +// RUN: %clang_cc1 -std=c++11 -triple i686-unknown-windows-msvc -fobjc-runtime=ios -fobjc-arc -Wno-objc-root-class -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,CHECK-DARWIN %s + +// non trivially copyable, forces inalloca +struct S { + S(const S &s) {} +}; + +@interface C +@end + +@implementation C +- (void)object:(id)obj struct:(S)s { +} +@end + +// CHECK-GNUSTEP: define internal void @_i_C__object_struct_(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca) +// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca) +// CHECK: %obj = getelementptr inbounds <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>, <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 2 +// CHECK: %[[INSTANCE:[0-9]+]] = load i8*, i8** %obj, align 4 +// CHECK: call void @objc_storeStrong(i8** %obj, i8* %[[INSTANCE]]) diff --git a/test/CodeGenOpenCL/addr-space-struct-arg.cl b/test/CodeGenOpenCL/addr-space-struct-arg.cl index d711f78d4ef0..6ea0aff0a074 100644 --- a/test/CodeGenOpenCL/addr-space-struct-arg.cl +++ b/test/CodeGenOpenCL/addr-space-struct-arg.cl @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -ffake-address-space-map -triple i686-pc-darwin | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -ffake-address-space-map -triple i686-pc-darwin | FileCheck -check-prefixes=COM,X86 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn-amdhsa-amd-amdgizcl | FileCheck -check-prefixes=COM,AMD %s typedef struct { int cells[9]; @@ -8,16 +9,57 @@ typedef struct { int cells[16]; } Mat4X4; +struct StructOneMember { + int2 x; +}; + +struct StructTwoMember { + int2 x; + int2 y; +}; + +// COM-LABEL: define void @foo Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) { Mat4X4 out; return out; } +// COM-LABEL: define {{.*}} void @ker +// Expect two mem copies: one for the argument "in", and one for +// the return value. +// X86: call void @llvm.memcpy.p0i8.p1i8.i32(i8* +// X86: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* +// AMD: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)* +// AMD: call void @llvm.memcpy.p1i8.p5i8.i64(i8 addrspace(1)* kernel void ker(global Mat3X3 *in, global Mat4X4 *out) { out[0] = foo(in[1]); } -// Expect two mem copies: one for the argument "in", and one for -// the return value. -// CHECK: call void @llvm.memcpy.p0i8.p1i8.i32(i8* -// CHECK: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* +// AMD-LABEL: define void @FuncOneMember(%struct.StructOneMember addrspace(5)* byval align 8 %u) +void FuncOneMember(struct StructOneMember u) { + u.x = (int2)(0, 0); +} + +// AMD-LABEL: define amdgpu_kernel void @KernelOneMember +// AMD-SAME: (<2 x i32> %[[u_coerce:.*]]) +// AMD: %[[u:.*]] = alloca %struct.StructOneMember, align 8, addrspace(5) +// AMD: %[[coerce_dive:.*]] = getelementptr inbounds %struct.StructOneMember, %struct.StructOneMember addrspace(5)* %[[u]], i32 0, i32 0 +// AMD: store <2 x i32> %[[u_coerce]], <2 x i32> addrspace(5)* %[[coerce_dive]] +// AMD: call void @FuncOneMember(%struct.StructOneMember addrspace(5)* byval align 8 %[[u]]) +kernel void KernelOneMember(struct StructOneMember u) { + FuncOneMember(u); +} + +// AMD-LABEL: define void @FuncTwoMember(%struct.StructTwoMember addrspace(5)* byval align 8 %u) +void FuncTwoMember(struct StructTwoMember u) { + u.x = (int2)(0, 0); +} + +// AMD-LABEL: define amdgpu_kernel void @KernelTwoMember +// AMD-SAME: (%struct.StructTwoMember %[[u_coerce:.*]]) +// AMD: %[[u:.*]] = alloca %struct.StructTwoMember, align 8, addrspace(5) +// AMD: store %struct.StructTwoMember %[[u_coerce]], %struct.StructTwoMember addrspace(5)* %[[u]] +// AMD: call void @FuncTwoMember(%struct.StructTwoMember addrspace(5)* byval align 8 %[[u]]) +kernel void KernelTwoMember(struct StructTwoMember u) { + FuncTwoMember(u); +} diff --git a/test/Driver/arm-execute-only.c b/test/Driver/arm-execute-only.c index a4854485e1e4..c226a7f3b4b1 100644 --- a/test/Driver/arm-execute-only.c +++ b/test/Driver/arm-execute-only.c @@ -1,39 +1,3 @@ -// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv6t2-eabi -### -mexecute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv6t2-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv7m-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv7m-eabi -### -mexecute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv7m-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.base-eabi -### -mexecute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv8m.base-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.main-eabi -### -mexecute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv8m.main-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - // RUN: not %clang -c -target thumbv6m-eabi -mexecute-only %s 2>&1 | \ // RUN: FileCheck --check-prefix CHECK-EXECUTE-ONLY-NOT-SUPPORTED %s @@ -45,42 +9,6 @@ // -mpure-code flag for GCC compatibility -// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv6t2-eabi -### -mpure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv6t2-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv7m-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv7m-eabi -### -mpure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv7m-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.base-eabi -### -mpure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv8m.base-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - -// RUN: %clang -target armv8m.main-eabi -### -mpure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY - -// RUN: %clang -target armv8m.main-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ -// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY - // RUN: not %clang -c -target thumbv6m-eabi -mpure-code %s 2>&1 | \ // RUN: FileCheck --check-prefix CHECK-EXECUTE-ONLY-NOT-SUPPORTED %s diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c index bad49942a4c4..e4b72d69ca3f 100644 --- a/test/Driver/clang_f_opts.c +++ b/test/Driver/clang_f_opts.c @@ -178,13 +178,6 @@ // CHECK-SLP-VECTORIZE: "-vectorize-slp" // CHECK-NO-SLP-VECTORIZE-NOT: "-vectorize-slp" -// RUN: %clang -### -S -fslp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-SLP-VECTORIZE-AGG %s -// RUN: %clang -### -S -fno-slp-vectorize-aggressive -fslp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-SLP-VECTORIZE-AGG %s -// RUN: %clang -### -S -fno-slp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SLP-VECTORIZE-AGG %s -// RUN: %clang -### -S -fslp-vectorize-aggressive -fno-slp-vectorize-aggressive %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SLP-VECTORIZE-AGG %s -// CHECK-SLP-VECTORIZE-AGG: "-vectorize-slp-aggressive" -// CHECK-NO-SLP-VECTORIZE-AGG-NOT: "-vectorize-slp-aggressive" - // RUN: %clang -### -S -fextended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-EXTENDED-IDENTIFIERS %s // RUN: not %clang -### -S -fno-extended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-NO-EXTENDED-IDENTIFIERS %s // CHECK-EXTENDED-IDENTIFIERS: "-cc1" diff --git a/test/Driver/darwin-version.c b/test/Driver/darwin-version.c index 8f08bb9dec4a..c11a2df37f98 100644 --- a/test/Driver/darwin-version.c +++ b/test/Driver/darwin-version.c @@ -10,6 +10,41 @@ // RUN: %clang -target armv6-apple-darwin9 -miphoneos-version-min=3.0 -c %s -### 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-VERSION-IOS3 %s // CHECK-VERSION-IOS3: "armv6k-apple-ios3.0.0" + +// RUN: env IPHONEOS_DEPLOYMENT_TARGET=11.0 \ +// RUN: %clang -target armv7-apple-ios9.0 -c -### %s 2> %t.err +// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS4 %s +// CHECK-VERSION-IOS4: invalid iOS deployment version 'IPHONEOS_DEPLOYMENT_TARGET=11.0' + +// RUN: %clang -target armv7-apple-ios9.0 -miphoneos-version-min=11.0 -c -### %s 2> %t.err +// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS5 %s +// CHECK-VERSION-IOS5: invalid iOS deployment version '-miphoneos-version-min=11.0' + +// RUN: %clang -target i386-apple-darwin -mios-simulator-version-min=11.0 -c -### %s 2> %t.err +// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS6 %s +// CHECK-VERSION-IOS6: invalid iOS deployment version '-mios-simulator-version-min=11.0' + +// RUN: %clang -target armv7-apple-ios11.1 -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS7 %s +// CHECK-VERSION-IOS7: thumbv7-apple-ios10.99.99 + +// RUN: env IPHONEOS_DEPLOYMENT_TARGET=11.0 \ +// RUN: %clang -target arm64-apple-ios11.0 -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS8 %s +// CHECK-VERSION-IOS8: arm64-apple-ios11.0.0 + +// RUN: %clang -target arm64-apple-ios11.0 -miphoneos-version-min=11.0 -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS9 %s +// CHECK-VERSION-IOS9: arm64-apple-ios11.0.0 + +// RUN: %clang -target x86_64-apple-darwin -mios-simulator-version-min=11.0 -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS10 %s +// CHECK-VERSION-IOS10: x86_64-apple-ios11.0.0 + +// RUN: %clang -target arm64-apple-ios11.1 -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS11 %s +// CHECK-VERSION-IOS11: arm64-apple-ios11.1.0 + // RUN: %clang -target i686-apple-darwin8 -c %s -### 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-VERSION-OSX4 %s // RUN: %clang -target i686-apple-darwin9 -mmacosx-version-min=10.4 -c %s -### 2>&1 | \ diff --git a/test/Driver/fuzzer.c b/test/Driver/fuzzer.c index e534a73a647f..989b3b9f6348 100644 --- a/test/Driver/fuzzer.c +++ b/test/Driver/fuzzer.c @@ -15,6 +15,14 @@ // // CHECK-LIBCXX-DARWIN: -lc++ + +// Check that we don't link in libFuzzer.a when producing a shared object. +// RUN: %clang -fsanitize=fuzzer %s -shared -o %t.so -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB-SO %s +// CHECK-NOLIB-SO-NOT: libLLVMFuzzer.a + +// RUN: %clang -fsanitize=fuzzer -fsanitize-coverage=trace-pc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-MSG %s +// CHECK-MSG-NOT: argument unused during compilation + int LLVMFuzzerTestOneInput(const char *Data, long Size) { return 0; } diff --git a/test/Driver/nios2-cpu.c b/test/Driver/nios2-cpu.c new file mode 100644 index 000000000000..d98f0384a66d --- /dev/null +++ b/test/Driver/nios2-cpu.c @@ -0,0 +1,26 @@ +// RUN: %clang -target nios2--- %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck %s + +// RUN: %clang -target nios2--- -mcpu=r1 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R1 %s +// RUN: %clang -target nios2--- -mcpu=nios2r1 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R1 %s +// RUN: %clang -target nios2--- -march=r1 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R1 %s +// RUN: %clang -target nios2--- -march=nios2r1 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R1 %s + +// RUN: %clang -target nios2--- -mcpu=r2 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R2 %s +// RUN: %clang -target nios2--- -mcpu=nios2r2 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R2 %s +// RUN: %clang -target nios2--- -march=r2 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R2 %s +// RUN: %clang -target nios2--- -march=nios2r2 %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-R2 %s + +// CHECK: "-triple" "nios2---" +// CHECK-R1: "-triple" "nios2---" +// CHECK-R1: "-target-cpu" "nios2r1" +// CHECK-R2: "-triple" "nios2---" +// CHECK-R2: "-target-cpu" "nios2r2" diff --git a/test/Driver/openmp-offload.c b/test/Driver/openmp-offload.c index 39eb41e6ac08..d43aa331c9dc 100644 --- a/test/Driver/openmp-offload.c +++ b/test/Driver/openmp-offload.c @@ -250,15 +250,15 @@ // // Compile for the powerpc device. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" // CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" @@ -267,15 +267,15 @@ // // Compile for the x86 device. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" // CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" @@ -398,25 +398,25 @@ // CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" // Create target 1 object. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // Create target 2 object. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" @@ -464,13 +464,13 @@ // CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" // Create target 1 object. -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" // CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" @@ -478,13 +478,13 @@ // CHK-UBJOBS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]" // Create target 2 object. -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" // CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" @@ -559,21 +559,21 @@ // CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" // Create target 1 object. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // Create target 2 object. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" @@ -589,3 +589,11 @@ // CHK-UBUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]" // CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs= // CHK-UBUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]" + +/// ########################################################################### + +/// Check -fopenmp-is-device is passed when compiling for the device. +// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s + +// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le--linux" {{.*}}.c" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" diff --git a/test/Driver/unavailable_aligned_allocation.cpp b/test/Driver/unavailable_aligned_allocation.cpp new file mode 100644 index 000000000000..cd75c08165d7 --- /dev/null +++ b/test/Driver/unavailable_aligned_allocation.cpp @@ -0,0 +1,54 @@ +// RUN: %clang -target x86_64-apple-macosx10.12 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// RUN: %clang -target arm64-apple-ios10 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// RUN: %clang -target arm64-apple-tvos10 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// RUN: %clang -target thumbv7-apple-watchos3 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.13 -mios-simulator-version-min=10 \ +// RUN: -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.13 -mtvos-simulator-version-min=10 \ +// RUN: -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.13 -mwatchos-simulator-version-min=3 \ +// RUN: -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=UNAVAILABLE +// +// UNAVAILABLE: "-faligned-alloc-unavailable" + +// RUN: %clang -target x86_64-apple-macosx10.13 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target arm64-apple-ios11 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target arm64-apple-tvos11 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target armv7k-apple-watchos4 -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target x86_64-unknown-linux-gnu -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.12 -mios-simulator-version-min=11 \ +// RUN: -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.12 -mtvos-simulator-version-min=11 \ +// RUN: -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// RUN: %clang -target x86_64-apple-macosx10.12 -mwatchos-simulator-version-min=4 \ +// RUN: -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=AVAILABLE +// +// AVAILABLE-NOT: "-faligned-alloc-unavailable" diff --git a/test/Driver/windows-cross.c b/test/Driver/windows-cross.c index 90fefbadfea1..0e688f0a26e7 100644 --- a/test/Driver/windows-cross.c +++ b/test/Driver/windows-cross.c @@ -80,3 +80,8 @@ // CHECK-ISYSTEM-AFTER: "-internal-isystem" "Windows Kits{{[/\\]}}10{{[/\\]}}Include{{[/\\]}}10.0.10586.0{{[/\\]}}um" // CHECK-ISYSTEM-AFTER: "-internal-isystem" "Windows Kits{{[/\\]}}10{{[/\\]}}Include{{[/\\]}}10.0.10586.0{{[/\\]}}shared" +// RUN: %clang -### -target armv7-windows-itanium -nostdinc -isystem-after "Windows Kits/10/Include/10.0.10586.0/ucrt" -c %s -o /dev/null 2>&1 \ +// RUN: | FileCheck %s --check-prefix CHECK-NOSTDINC-ISYSTEM-AFTER +// CHECK-NOSTDINC-ISYSTEM-AFTER: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NOSTDINC-ISYSTEM-AFTER-NOT: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" +// CHECK-NOSTDINC-ISYSTEM-AFTER: "-internal-isystem" "Windows Kits{{[/\\]}}10{{[/\\]}}Include{{[/\\]}}10.0.10586.0{{[/\\]}}ucrt" diff --git a/test/FixIt/fixit-format-darwin.m b/test/FixIt/fixit-format-darwin.m index 077cc0cf21bc..54d25d92c2b3 100644 --- a/test/FixIt/fixit-format-darwin.m +++ b/test/FixIt/fixit-format-darwin.m @@ -8,12 +8,15 @@ int printf(const char * restrict, ...); #if __LP64__ +typedef long CFIndex; typedef long NSInteger; typedef unsigned long NSUInteger; #else +typedef int CFIndex; typedef int NSInteger; typedef unsigned int NSUInteger; #endif +CFIndex getCFIndex(); NSInteger getNSInteger(); NSUInteger getNSUInteger(); @@ -74,3 +77,10 @@ void bug33447() { Outer2("test 9: %s %s", getNSInteger(), getNSInteger()); // CHECK: Outer2("test 9: %ld %ld", (long)getNSInteger(), (long)getNSInteger()); } + +void testCFIndex() { + printf("test 10: %s", getCFIndex()); + // CHECK: printf("test 10: %ld", (long)getCFIndex()); + printf("test 11: %s %s", getCFIndex(), getCFIndex()); + // CHECK: printf("test 11: %ld %ld", (long)getCFIndex(), (long)getCFIndex()); +} diff --git a/test/FixIt/format-darwin.m b/test/FixIt/format-darwin.m index 170bb09fb904..fcc81036fcf3 100644 --- a/test/FixIt/format-darwin.m +++ b/test/FixIt/format-darwin.m @@ -7,13 +7,14 @@ int printf(const char * restrict, ...); #if __LP64__ +typedef long CFIndex; typedef long NSInteger; typedef unsigned long NSUInteger; typedef int SInt32; typedef unsigned int UInt32; #else - +typedef int CFIndex; typedef int NSInteger; typedef unsigned int NSUInteger; typedef long SInt32; @@ -27,6 +28,7 @@ typedef enum NSIntegerEnum : NSInteger { EnumValueB } NSIntegerEnum; +CFIndex getCFIndex(); NSInteger getNSInteger(); NSUInteger getNSUInteger(); SInt32 getSInt32(); @@ -55,6 +57,11 @@ void testCorrectionInAllCases() { // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)" + + printf("%s", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}} + + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)" } @interface Foo { @@ -120,6 +127,11 @@ void testWarn() { // CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)" + + printf("%d", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}} + + // CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" + // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)" } void testPreserveHex() { @@ -167,6 +179,10 @@ void testWarn() { printf("%ld", getNSIntegerEnum()); // expected-warning{{enum values with underlying type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} // CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)" + + printf("%ld", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}} + + // CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)" } void testPreserveHex() { @@ -218,6 +234,11 @@ void testCasts() { // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:31}:"(long)" + + printf("%s", (CFIndex)0); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}} + + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:25}:"(long)" } void testCapitals() { diff --git a/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext b/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext index aeea583de4d4..730dc4a0d5b1 100644 --- a/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext +++ b/test/Frontend/Inputs/optimization-remark-with-hotness-sample.proftext @@ -1,7 +1,7 @@ foo:0:0 0: 0 bar:29:29 - 6: foo:0 + 9: foo:0 main:0:0 0: 0 bar:0 diff --git a/test/Frontend/optimization-remark-with-hotness.c b/test/Frontend/optimization-remark-with-hotness.c index 30ead64b8eb5..875fc75ae159 100644 --- a/test/Frontend/optimization-remark-with-hotness.c +++ b/test/Frontend/optimization-remark-with-hotness.c @@ -15,12 +15,14 @@ // RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \ // RUN: -fprofile-sample-use=%t-sample.profdata -Rpass=inline \ // RUN: -Rpass-analysis=inline -Rpass-missed=inline \ -// RUN: -fdiagnostics-show-hotness -verify +// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 \ +// RUN: -verify // The clang version of the previous test. // RUN: %clang -target x86_64-apple-macosx10.9 %s -c -emit-llvm -o /dev/null \ // RUN: -fprofile-instr-use=%t.profdata -Rpass=inline \ // RUN: -Rpass-analysis=inline -Rpass-missed=inline \ -// RUN: -fdiagnostics-show-hotness -Xclang -verify +// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 \ +// RUN: -Xclang -verify // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \ // RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \ // RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \ @@ -28,11 +30,18 @@ // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \ // RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \ // RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \ -// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \ +// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \ // RUN: -check-prefix=HOTNESS_OFF %s // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \ // RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \ -// RUN: -Rpass=inline -Rpass-analysis=inline -fdiagnostics-show-hotness 2>&1 \ +// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \ +// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness \ +// RUN: -fdiagnostics-hotness-threshold=100 2>&1 \ +// RUN: | FileCheck -allow-empty -check-prefix=THRESHOLD %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \ +// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \ +// RUN: -Rpass=inline -Rpass-analysis=inline \ +// RUN: -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=10 2>&1 \ // RUN: | FileCheck -check-prefix=NO_PGO %s int foo(int x, int y) __attribute__((always_inline)); @@ -43,7 +52,10 @@ int sum = 0; void bar(int x) { // HOTNESS_OFF: foo inlined into bar // HOTNESS_OFF-NOT: hotness: + // THRESHOLD-NOT: inlined + // THRESHOLD-NOT: hotness // NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information + // NO_PGO: '-fdiagnostics-hotness-threshold=' requires profile-guided optimization information // expected-remark@+2 {{foo should always be inlined (cost=always) (hotness: 30)}} // expected-remark@+1 {{foo inlined into bar (hotness: 30)}} sum += foo(x, x - 2); diff --git a/test/Index/ctor-init-source-loc.cpp b/test/Index/ctor-init-source-loc.cpp new file mode 100644 index 000000000000..ff93e58092da --- /dev/null +++ b/test/Index/ctor-init-source-loc.cpp @@ -0,0 +1,117 @@ +// RUN: c-index-test -test-load-source all %s -fno-delayed-template-parsing | FileCheck %s +template<typename MyBase> +struct Derived: MyBase::InnerIterator +{ + Derived() : MyBase::InnerIterator() {} +// CHECK: TypeRef=MyBase:2:19 Extent=[5:17 - 5:23] +}; + +template<typename MyBase> +struct Derived2: MyBase::Deeper::InnerIterator +{ + Derived2() : MyBase::Deeper::InnerIterator() {} +// CHECK: TypeRef=MyBase:9:19 Extent=[12:18 - 12:24] +}; + +template<typename Q> +struct Templ; + +template<typename MyBase> +struct Derived3: Templ<MyBase>::InnerIterator +{ + Derived3() : Templ<MyBase>::InnerIterator() {} +// CHECK: TemplateRef=Templ:17:8 Extent=[22:18 - 22:23] +// CHECK: TypeRef=MyBase:19:19 Extent=[22:24 - 22:30] +}; + + +struct Outer { + template <typename Q> + struct Inner { + typedef Q Parm; + }; +}; + +template<typename Q> +struct Derived4: Outer::Inner<Q>::Parm +{ + Derived4() : Outer::Inner<Q>::Parm() {} +// CHECK: TypeRef=struct Outer:28:8 Extent=[38:18 - 38:23] +// CHECK: TemplateRef=Inner:30:12 Extent=[38:25 - 38:30] +// CHECK: TypeRef=Q:35:19 Extent=[38:31 - 38:32] +}; + +template<typename Q> +struct Derived5: Outer::Inner<Q>::Parm::InnerIterator +{ + Derived5() : Outer::Inner<Q>::Parm::InnerIterator() {} +// CHECK: TypeRef=struct Outer:28:8 Extent=[47:18 - 47:23] +// CHECK: TemplateRef=Inner:30:12 Extent=[47:25 - 47:30] +// CHECK: TypeRef=Q:44:19 Extent=[47:31 - 47:32] +}; + +template<typename Q> +struct Derived6: Outer::Inner<Q> +{ + Derived6() : Outer::Inner<Q>() {} +// CHECK: TypeRef=struct Outer:28:8 Extent=[56:18 - 56:23] +// CHECK: TemplateRef=Inner:30:12 Extent=[56:25 - 56:30] +// CHECK: TypeRef=Q:53:19 Extent=[56:31 - 56:32] +}; + +struct Base {}; + +struct Derived7: Outer::Inner<Base>::Parm +{ + Derived7() : Outer::Inner<Base>::Parm() {} +// CHECK: TypeRef=struct Outer:28:8 Extent=[66:18 - 66:23] +// CHECK: TemplateRef=Inner:30:12 Extent=[66:25 - 66:30] +// CHECK: TypeRef=struct Base:62:8 Extent=[66:31 - 66:35] +}; + +struct Derived8: Outer::Inner<Base> +{ + Derived8() : Outer::Inner<Base>() {} +// CHECK: TypeRef=struct Outer:28:8 Extent=[74:18 - 74:23] +// CHECK: TemplateRef=Inner:30:12 Extent=[74:25 - 74:30] +// CHECK: TypeRef=struct Base:62:8 Extent=[74:31 - 74:35] +}; + +namespace Namespace { + template<typename Q> struct Templ; + + struct Outer { + template <typename Q> + struct Inner { + typedef Q Parm; + }; + }; +} + +template<typename MyBase> +struct Derived9: Namespace::Templ<MyBase>::InnerIterator +{ + Derived9() : Namespace::Templ<MyBase>::InnerIterator() {} +// CHECK: NamespaceRef=Namespace:80:11 Extent=[94:18 - 94:27] +// CHECK: TemplateRef=Templ:81:33 Extent=[94:29 - 94:34] +// CHECK: TypeRef=MyBase:91:19 Extent=[94:35 - 94:41] +}; + +template<typename MyBase> +struct Derived10: Namespace::Templ<MyBase> +{ + Derived10() : Namespace::Templ<MyBase>() {} +// CHECK: NamespaceRef=Namespace:80:11 Extent=[103:19 - 103:28] +// CHECK: TemplateRef=Templ:81:33 Extent=[103:30 - 103:35] +// CHECK: TypeRef=MyBase:100:19 Extent=[103:36 - 103:42] +}; + +template<typename MyBase> +struct Derived11: Namespace::Outer::Inner<MyBase>::Parm +{ + Derived11() : Namespace::Outer::Inner<MyBase>::Parm() {} +// CHECK: NamespaceRef=Namespace:80:11 Extent=[112:19 - 112:28] +// CHECK: TypeRef=struct Namespace::Outer:83:12 Extent=[112:30 - 112:35] +// CHECK: TemplateRef=Inner:85:16 Extent=[112:37 - 112:42] +// CHECK: TypeRef=MyBase:109:19 Extent=[112:43 - 112:49] +}; diff --git a/test/Index/get-cursor.cpp b/test/Index/get-cursor.cpp index 27f75938fedd..8aa12d5bc310 100644 --- a/test/Index/get-cursor.cpp +++ b/test/Index/get-cursor.cpp @@ -145,6 +145,13 @@ void test(TestColl coll) { const int operator""_toint(unsigned long long val) { return int(val); } +// noexcept specifications +void f_noexcept() noexcept; +template <class T> void f_computed_noexcept(T t) noexcept(noexcept(t+t)); +void f_dynamic_noexcept_none() throw(); +void f_dynamic_noexcept() throw(int); +void f_dynamic_noexcept_any() throw(...); + // RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s // CHECK-COMPLETION-1: CXXConstructor=X:6:3 // CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )} @@ -209,11 +216,11 @@ const int operator""_toint(unsigned long long val) { return int(val); } // RUN: c-index-test -cursor-at=%s:66:23 %s | FileCheck -check-prefix=CHECK-TEMPLSPEC %s // CHECK-TEMPLSPEC: 66:23 ClassDecl=TC:66:23 (Definition) [Specialization of TC:59:7] Extent=[66:1 - 66:31] Spelling=TC ([66:23 - 66:25]) -// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s +// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -cursor-at=%s:149:6 -cursor-at=%s:150:25 -cursor-at=%s:151:6 -cursor-at=%s:152:6 -cursor-at=%s:153:6 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s // CHECK-SPELLING: 69:3 CXXConstructor=A:69:3 (default constructor) Extent=[69:3 - 69:6] Spelling=A ([69:3 - 69:4]) // CHECK-SPELLING: 70:11 CXXDestructor=~A:70:11 (virtual) Extent=[70:3 - 70:15] Spelling=~A ([70:11 - 70:13]) // CHECK-SPELLING: 73:6 CXXMethod=operator=:73:6 Extent=[73:3 - 73:25] Spelling=operator= ([73:6 - 73:15]) -// CHECK-SPELLING: 74:6 CXXMethod=operator=:74:6 Extent=[74:3 - 74:29] Spelling=operator= ([74:6 - 74:15]) +// CHECK-SPELLING: 74:6 CXXMethod=operator=:74:6 (noexcept) Extent=[74:3 - 74:29] Spelling=operator= ([74:6 - 74:15]) // CHECK-SPELLING: 77:8 CXXMethod=operator+:77:8 (const) Extent=[77:3 - 77:25] Spelling=operator+ ([77:8 - 77:17]) // CHECK-SPELLING: 78:8 CXXMethod=operator-:78:8 (const) Extent=[78:3 - 78:25] Spelling=operator- ([78:8 - 78:17]) // CHECK-SPELLING: 79:8 CXXMethod=operator~:79:8 (const) Extent=[79:3 - 79:25] Spelling=operator~ ([79:8 - 79:17]) @@ -257,8 +264,14 @@ const int operator""_toint(unsigned long long val) { return int(val); } // CHECK-SPELLING: 130:6 CXXMethod=operator():130:6 (const) Extent=[130:3 - 130:37] Spelling=operator() ([130:6 - 130:16]) // CHECK-SPELLING: 132:12 CXXConversion=operator bool:132:12 (const) Extent=[132:3 - 132:33] Spelling=operator bool ([132:12 - 132:25]) // CHECK-SPELLING: 146:11 FunctionDecl=operator""_toint:146:11 (Definition) Extent=[146:1 - 146:72] Spelling=operator""_toint ([146:11 - 146:27]) +// CHECK-SPELLING: 149:6 FunctionDecl=f_noexcept:149:6 (noexcept) Extent=[149:1 - 149:27] Spelling=f_noexcept ([149:6 - 149:16]) +// CHECK-SPELLING: 150:25 FunctionTemplate=f_computed_noexcept:150:25 (computed-noexcept) Extent=[150:1 - 150:73] Spelling=f_computed_noexcept ([150:25 - 150:44]) +// CHECK-SPELLING: 151:6 FunctionDecl=f_dynamic_noexcept_none:151:6 (noexcept dynamic none) Extent=[151:1 - 151:39] Spelling=f_dynamic_noexcept_none ([151:6 - 151:29]) +// CHECK-SPELLING: 152:6 FunctionDecl=f_dynamic_noexcept:152:6 (noexcept dynamic) Extent=[152:1 - 152:37] Spelling=f_dynamic_noexcept ([152:6 - 152:24]) +// CHECK-SPELLING: 153:6 FunctionDecl=f_dynamic_noexcept_any:153:6 (noexcept dynamic any) Extent=[153:1 - 153:41] Spelling=f_dynamic_noexcept_any ([153:6 - 153:28]) // RUN: c-index-test -cursor-at=%s:141:13 -cursor-at=%s:141:18 -cursor-at=%s:142:11 -std=c++11 %s | FileCheck -check-prefix=CHECK-FORRANGE %s // CHECK-FORRANGE: 141:13 VarDecl=lv:141:13 (Definition) Extent=[141:8 - 141:17] Spelling=lv ([141:13 - 141:15]) // CHECK-FORRANGE: 141:18 DeclRefExpr=coll:140:20 Extent=[141:18 - 141:22] Spelling=coll ([141:18 - 141:22]) // CHECK-FORRANGE: 142:11 DeclRefExpr=lv:141:13 Extent=[142:11 - 142:13] Spelling=lv ([142:11 - 142:13]) + diff --git a/test/Index/linkage.c b/test/Index/linkage.c index ab006590b61c..b0dcb30990a0 100644 --- a/test/Index/linkage.c +++ b/test/Index/linkage.c @@ -20,7 +20,7 @@ void f16(void) { // CHECK: EnumDecl=Baz:3:6 (Definition)linkage=External -// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=External +// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=NoLinkage // CHECK: VarDecl=x:4:5linkage=External // CHECK: FunctionDecl=foo:5:6linkage=External // CHECK: VarDecl=w:6:12linkage=Internal diff --git a/test/Modules/Inputs/F.framework/Headers/F.h b/test/Modules/Inputs/F.framework/Headers/F.h new file mode 100644 index 000000000000..4f705f00e1ac --- /dev/null +++ b/test/Modules/Inputs/F.framework/Headers/F.h @@ -0,0 +1 @@ +// F.h diff --git a/test/Modules/Inputs/F.framework/Modules/module.modulemap b/test/Modules/Inputs/F.framework/Modules/module.modulemap new file mode 100644 index 000000000000..e414776c536b --- /dev/null +++ b/test/Modules/Inputs/F.framework/Modules/module.modulemap @@ -0,0 +1,7 @@ +framework module F [extern_c] [system] { + umbrella header "F.h" + module * { + export * + } + export * +} diff --git a/test/Modules/Inputs/F.framework/Modules/module.private.modulemap b/test/Modules/Inputs/F.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..69486a2a6410 --- /dev/null +++ b/test/Modules/Inputs/F.framework/Modules/module.private.modulemap @@ -0,0 +1,7 @@ +module F.Private [system] { + explicit module NS { + header "NS.h" + export * + } + export * +} diff --git a/test/Modules/Inputs/F.framework/PrivateHeaders/NS.h b/test/Modules/Inputs/F.framework/PrivateHeaders/NS.h new file mode 100644 index 000000000000..5e947ba90518 --- /dev/null +++ b/test/Modules/Inputs/F.framework/PrivateHeaders/NS.h @@ -0,0 +1,19 @@ +struct NS { + int a; + int b; +}; + +enum NSE { + FST = 22, + SND = 43, + TRD = 55 +}; + +#define NS_ENUM(_type, _name) \ + enum _name : _type _name; \ + enum _name : _type + +typedef NS_ENUM(int, NSMyEnum) { + MinX = 11, + MinXOther = MinX, +}; diff --git a/test/Modules/Inputs/lookup-assert-protocol/Base.h b/test/Modules/Inputs/lookup-assert-protocol/Base.h new file mode 100644 index 000000000000..5c9506fa5cd3 --- /dev/null +++ b/test/Modules/Inputs/lookup-assert-protocol/Base.h @@ -0,0 +1,3 @@ +@protocol BaseProtocol +- (void) test; +@end diff --git a/test/Modules/Inputs/lookup-assert-protocol/Derive.h b/test/Modules/Inputs/lookup-assert-protocol/Derive.h new file mode 100644 index 000000000000..fdcde6158a7c --- /dev/null +++ b/test/Modules/Inputs/lookup-assert-protocol/Derive.h @@ -0,0 +1,4 @@ +#include "Base.h" +@protocol DerivedProtocol<BaseProtocol> +- (void) test2; +@end diff --git a/test/Modules/Inputs/lookup-assert-protocol/H3.h b/test/Modules/Inputs/lookup-assert-protocol/H3.h new file mode 100644 index 000000000000..3d8f878905df --- /dev/null +++ b/test/Modules/Inputs/lookup-assert-protocol/H3.h @@ -0,0 +1 @@ +#include "Base.h" diff --git a/test/Modules/Inputs/lookup-assert-protocol/module.map b/test/Modules/Inputs/lookup-assert-protocol/module.map new file mode 100644 index 000000000000..e8a89eb095a4 --- /dev/null +++ b/test/Modules/Inputs/lookup-assert-protocol/module.map @@ -0,0 +1,4 @@ +module X { + header "H3.h" + export * +} diff --git a/test/Modules/Inputs/preprocess-decluse/a.h b/test/Modules/Inputs/preprocess-decluse/a.h new file mode 100644 index 000000000000..17ab46c84892 --- /dev/null +++ b/test/Modules/Inputs/preprocess-decluse/a.h @@ -0,0 +1 @@ +// a.h diff --git a/test/Modules/Inputs/preprocess-decluse/a.modulemap b/test/Modules/Inputs/preprocess-decluse/a.modulemap new file mode 100644 index 000000000000..47105fe36399 --- /dev/null +++ b/test/Modules/Inputs/preprocess-decluse/a.modulemap @@ -0,0 +1 @@ +module A { textual header "a.h" } diff --git a/test/Modules/Inputs/preprocess-decluse/b.h b/test/Modules/Inputs/preprocess-decluse/b.h new file mode 100644 index 000000000000..2243de1baf9a --- /dev/null +++ b/test/Modules/Inputs/preprocess-decluse/b.h @@ -0,0 +1 @@ +#include "a.h" diff --git a/test/Modules/Inputs/preprocess-decluse/b.modulemap b/test/Modules/Inputs/preprocess-decluse/b.modulemap new file mode 100644 index 000000000000..bd0bdf0e2e94 --- /dev/null +++ b/test/Modules/Inputs/preprocess-decluse/b.modulemap @@ -0,0 +1 @@ +module B { header "b.h" use A } diff --git a/test/Modules/Inputs/preprocess-decluse/main.modulemap b/test/Modules/Inputs/preprocess-decluse/main.modulemap new file mode 100644 index 000000000000..0392c846ce99 --- /dev/null +++ b/test/Modules/Inputs/preprocess-decluse/main.modulemap @@ -0,0 +1 @@ +module Main { use B } diff --git a/test/Modules/diag-flags.cpp b/test/Modules/diag-flags.cpp index 31d2fe4439b8..ada90d24b791 100644 --- a/test/Modules/diag-flags.cpp +++ b/test/Modules/diag-flags.cpp @@ -41,4 +41,4 @@ import diag_flags; #else // expected-no-diagnostics #endif -unsigned n = sizeof(Padded); +int arr[sizeof(Padded)]; diff --git a/test/Modules/elaborated-type-specifier-from-hidden-module.m b/test/Modules/elaborated-type-specifier-from-hidden-module.m index 0ca1c24bba00..571ccb9d95c0 100644 --- a/test/Modules/elaborated-type-specifier-from-hidden-module.m +++ b/test/Modules/elaborated-type-specifier-from-hidden-module.m @@ -4,12 +4,11 @@ @import ElaboratedTypeStructs.Empty; // The structs are now hidden. struct S1 *x; struct S2 *y; -// FIXME: compatible definition should not be an error. -struct S2 { int x; }; // expected-error {{redefinition}} +struct S2 { int x; }; struct S3 *z; // Incompatible definition. -struct S3 { float y; }; // expected-error {{redefinition}} -// expected-note@elaborated-type-structs.h:* 2 {{previous definition is here}} +struct S3 { float y; }; // expected-error {{has incompatible definitions}} // expected-note {{field has name}} +// expected-note@Inputs/elaborated-type-structs.h:3 {{field has name}} @import ElaboratedTypeStructs.Structs; diff --git a/test/Modules/lookup-assert-protocol.m b/test/Modules/lookup-assert-protocol.m new file mode 100644 index 000000000000..3c093f1bf156 --- /dev/null +++ b/test/Modules/lookup-assert-protocol.m @@ -0,0 +1,17 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/lookup-assert-protocol %s -verify +// expected-no-diagnostics + +#include "Derive.h" +#import <H3.h> + +__attribute__((objc_root_class)) +@interface Thing<DerivedProtocol> +@end + +@implementation Thing +- (void)test { +} +- (void)test2 { +} +@end diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index c94940c73eb6..6e01e989a374 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -968,6 +968,24 @@ S9 s9; // expected-error@second.h:* {{'NestedNamespaceSpecifier::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'P9::I' (aka 'int')}} // expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'O9::I' (aka 'int')}} #endif + +namespace N10 { +#if defined(FIRST) +inline namespace A { struct X {}; } +struct S10 { + A::X x; +}; +#elif defined(SECOND) +inline namespace B { struct X {}; } +struct S10 { + B::X x; +}; +#else +S10 s10; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::N10::S10::x' from module 'SecondModule' is not present in definition of 'NestedNamespaceSpecifier::N10::S10' in module 'FirstModule'}} +// expected-note@first.h:* {{declaration of 'x' does not match}} +#endif +} } namespace TemplateSpecializationType { @@ -1070,6 +1088,40 @@ S4 s4; // expected-error@first.h:* {{'TemplateArgument::S4::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S4' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'x' does not match}} #endif + +#if defined(FIRST) +template <class T> struct U5 {}; +struct S5 { + U5<int> x; +}; +#elif defined(SECOND) +template <class T> struct U5 {}; +struct S5 { + U5<short> x; +}; +#else +S5 s5; +// expected-error@first.h:* {{'TemplateArgument::S5::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S5' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif + +#if defined(FIRST) +template <class T> struct U6 {}; +struct S6 { + U6<int> x; + U6<short> y; +}; +#elif defined(SECOND) +template <class T> struct U6 {}; +struct S6 { + U6<short> y; + U6<int> x; +}; +#else +S6 s6; +// expected-error@second.h:* {{'TemplateArgument::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}} +#endif } namespace TemplateTypeParmType { @@ -1762,6 +1814,22 @@ struct S2 { #else S2 s2; #endif + +#if defined(FIRST) +using A3 = const int; +using B3 = volatile A3; +struct S3 { + B3 x = 1; +}; +#elif defined(SECOND) +using A3 = volatile const int; +using B3 = A3; +struct S3 { + B3 x = 1; +}; +#else +S3 s3; +#endif } // Keep macros contained to one file. diff --git a/test/Modules/preprocess-decluse.cpp b/test/Modules/preprocess-decluse.cpp new file mode 100644 index 000000000000..5c87e0dddac2 --- /dev/null +++ b/test/Modules/preprocess-decluse.cpp @@ -0,0 +1,18 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \ +// RUN: -fmodule-name=B -emit-module -o %t/b.pcm \ +// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/a.modulemap \ +// RUN: -x c++-module-map %S/Inputs/preprocess-decluse/b.modulemap +// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \ +// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/main.modulemap \ +// RUN: -fmodule-file=%t/b.pcm -fmodule-name=Main %s -verify +// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \ +// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/main.modulemap \ +// RUN: -fmodule-file=%t/b.pcm -fmodule-name=Main %s \ +// RUN: -E -frewrite-imports -o %t/rewrite.ii +// RUN: %clang_cc1 -fmodules -fmodules-strict-decluse -I%S/Inputs/preprocess-decluse \ +// RUN: -fmodule-map-file=%S/Inputs/preprocess-decluse/main.modulemap \ +// RUN: -fmodule-name=Main %t/rewrite.ii -verify + +// expected-no-diagnostics +#include "b.h" diff --git a/test/Modules/redefinition-c-tagtypes.m b/test/Modules/redefinition-c-tagtypes.m new file mode 100644 index 000000000000..a01f11bd74c8 --- /dev/null +++ b/test/Modules/redefinition-c-tagtypes.m @@ -0,0 +1,48 @@ +// RUN: rm -rf %t.cache +// RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \ +// RUN: -fimplicit-module-maps -F%S/Inputs -verify +// RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \ +// RUN: -fimplicit-module-maps -F%S/Inputs -DCHANGE_TAGS -verify +#include "F/F.h" + +#ifndef CHANGE_TAGS +// expected-no-diagnostics +#endif + +struct NS { + int a; +#ifndef CHANGE_TAGS + int b; +#else + int c; // expected-note {{field has name 'c' here}} + // expected-error@redefinition-c-tagtypes.m:12 {{type 'struct NS' has incompatible definitions}} + // expected-note@Inputs/F.framework/PrivateHeaders/NS.h:3 {{field has name 'b' here}} +#endif +}; + +enum NSE { + FST = 22, +#ifndef CHANGE_TAGS + SND = 43, +#else + SND = 44, // expected-note {{enumerator 'SND' with value 44 here}} + // expected-error@redefinition-c-tagtypes.m:23 {{type 'enum NSE' has incompatible definitions}} + // expected-note@Inputs/F.framework/PrivateHeaders/NS.h:8 {{enumerator 'SND' with value 43 here}} +#endif + TRD = 55 +}; + +#define NS_ENUM(_type, _name) \ + enum _name : _type _name; \ + enum _name : _type + +typedef NS_ENUM(int, NSMyEnum) { + MinX = 11, +#ifndef CHANGE_TAGS + MinXOther = MinX, +#else + MinXOther = TRD, // expected-note {{enumerator 'MinXOther' with value 55 here}} + // expected-error@redefinition-c-tagtypes.m:39 {{type 'enum NSMyEnum' has incompatible definitions}} + // expected-note@Inputs/F.framework/PrivateHeaders/NS.h:18 {{enumerator 'MinXOther' with value 11 here}} +#endif +}; diff --git a/test/Modules/redefinition-same-header.m b/test/Modules/redefinition-same-header.m index f1c6cbbcaa2e..8c180f643225 100644 --- a/test/Modules/redefinition-same-header.m +++ b/test/Modules/redefinition-same-header.m @@ -6,15 +6,7 @@ // expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}} // expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}} // expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}} +// expected-warning@Inputs/SameHeader/C.h:9 {{typedef requires a name}} -// expected-error@Inputs/SameHeader/C.h:5 {{redefinition of 'aaa'}} -// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}} -// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}} -// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}} - -// expected-error@Inputs/SameHeader/C.h:9 {{redefinition of 'fd_set'}} -// expected-note-re@Inputs/SameHeader/B.h:3 {{'{{.*}}C.h' included multiple times, additional include site in header from module 'X.B'}} -// expected-note@Inputs/SameHeader/module.modulemap:6 {{X.B defined here}} -// expected-note-re@redefinition-same-header.m:20 {{'{{.*}}C.h' included multiple times, additional include site here}} #include "A.h" // maps to a modular #include "C.h" // textual include diff --git a/test/OpenMP/parallel_codegen.cpp b/test/OpenMP/parallel_codegen.cpp index c43533c6c194..23b323778b47 100644 --- a/test/OpenMP/parallel_codegen.cpp +++ b/test/OpenMP/parallel_codegen.cpp @@ -64,7 +64,7 @@ int main (int argc, char **argv) { // CHECK: call {{.*}}void @{{.+terminate.*|abort}}( // CHECK-NEXT: unreachable // CHECK-NEXT: } -// CHECK-DEBUG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* [[VLA_ADDR:%[^)]+]]) +// CHECK-DEBUG: define internal void [[OMP_OUTLINED_DEBUG:@.+]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* [[VLA_ADDR:%[^)]+]]) // CHECK-DEBUG-SAME: #[[FN_ATTRS:[0-9]+]] // CHECK-DEBUG: store i32* [[VLA_ADDR]], i32** [[VLA_PTR_ADDR:%.+]], // CHECK-DEBUG: [[VLA_REF:%.+]] = load i32*, i32** [[VLA_PTR_ADDR]] @@ -80,6 +80,8 @@ int main (int argc, char **argv) { // CHECK-DAG: declare {{.*}}void @__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...) // CHECK-DEBUG-DAG: define linkonce_odr void [[FOO]](i32 %argc) // CHECK-DEBUG-DAG: declare void @__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...) +// CHECK-DEBUG-DAG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* [[VLA_ADDR:%[^)]+]]) +// CHECK-DEBUG-DAG: call void [[OMP_OUTLINED_DEBUG]] // CHECK: define linkonce_odr {{[a-z\_\b]*[ ]?i32}} [[TMAIN]](i8** %argc) // CHECK: store i8** %argc, i8*** [[ARGC_ADDR:%.+]], diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp index aaaf5fae5729..c457045c17c7 100644 --- a/test/OpenMP/target_codegen.cpp +++ b/test/OpenMP/target_codegen.cpp @@ -117,10 +117,10 @@ int foo(int n) { // CHECK-DAG: [[P]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR:%[^,]+]], i32 0, i32 0 // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BPR]], i32 0, i32 [[IDX0:[0-9]+]] // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR]], i32 0, i32 [[IDX0]] - // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] - // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] - // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[BP0:%[^,]+]], i[[SZ]]* [[CBPADDR0]] + // CHECK-DAG: store i[[SZ]] [[P0:%[^,]+]], i[[SZ]]* [[CPADDR0]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4 @@ -144,17 +144,17 @@ int foo(int n) { // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0 - // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] - // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] - // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[BP0:%[^,]+]], i[[SZ]]* [[CBPADDR0]] + // CHECK-DAG: store i[[SZ]] [[P0:%[^,]+]], i[[SZ]]* [[CPADDR0]] // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1 - // CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] - // CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] - // CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P1]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[BP1:%[^,]+]], i[[SZ]]* [[CBPADDR1]] + // CHECK-DAG: store i[[SZ]] [[P1:%[^,]+]], i[[SZ]]* [[CPADDR1]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] @@ -198,87 +198,89 @@ int foo(int n) { // CHECK-DAG: [[PR]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P:%[^,]+]], i32 0, i32 0 // CHECK-DAG: [[SR]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S:%[^,]+]], i32 0, i32 0 - // CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:[0-9]+]] + // CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]] // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX0]] // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX0]] - // CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:[0-9]+]] + // CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]] // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX1]] // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX1]] - // CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:[0-9]+]] + // CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]] // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX2]] // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX2]] - // CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:[0-9]+]] + // CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]] // CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX3]] // CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX3]] - // CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:[0-9]+]] + // CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]] // CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX4]] // CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX4]] - // CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:[0-9]+]] + // CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:5]] // CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX5]] // CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX5]] - // CHECK-DAG: [[SADDR6:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX6:[0-9]+]] + // CHECK-DAG: [[SADDR6:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX6:6]] // CHECK-DAG: [[BPADDR6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX6]] // CHECK-DAG: [[PADDR6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX6]] - // CHECK-DAG: [[SADDR7:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX7:[0-9]+]] + // CHECK-DAG: [[SADDR7:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX7:7]] // CHECK-DAG: [[BPADDR7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX7]] // CHECK-DAG: [[PADDR7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX7]] - // CHECK-DAG: [[SADDR8:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX8:[0-9]+]] + // CHECK-DAG: [[SADDR8:%.+]] = getelementptr inbounds [9 x i[[SZ]]], [9 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX8:8]] // CHECK-DAG: [[BPADDR8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BP]], i32 0, i32 [[IDX8]] // CHECK-DAG: [[PADDR8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[P]], i32 0, i32 [[IDX8]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. - // CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* - // CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* - // CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8* - // CHECK-DAG: [[P1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8* - // CHECK-DAG: store i8* [[BP1]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P1]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}} - // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8* - // CHECK-DAG: [[P3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8* - // CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8* - // CHECK-DAG: [[P4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP5:%[^,]+]] = bitcast float* %{{.+}} to i8* - // CHECK-DAG: [[P5:%[^,]+]] = bitcast float* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP5]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P5]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8* - // CHECK-DAG: [[P6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP6]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P6]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP7:%[^,]+]] = bitcast double* %{{.+}} to i8* - // CHECK-DAG: [[P7:%[^,]+]] = bitcast double* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP7]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P7]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* {{%[^,]+}} - - // CHECK-DAG: [[BP8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8* - // CHECK-DAG: [[P8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP8]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P8]], i8** {{%[^,]+}} - // CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* {{%[^,]+}} + // CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR2]] + // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR2]] + // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR2]] + + // CHECK-DAG: [[CBPADDR6:%.+]] = bitcast i8** [[BPADDR6]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR6:%.+]] = bitcast i8** [[PADDR6]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CBPADDR6]] + // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CPADDR6]] + // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR6]] + + // CHECK-DAG: [[CBPADDR5:%.+]] = bitcast i8** [[BPADDR5]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR5:%.+]] = bitcast i8** [[PADDR5]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CBPADDR5]] + // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CPADDR5]] + // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR5]] + + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CBPADDR0]] + // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CPADDR0]] + // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR0]] + + // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to [10 x float]** + // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to [10 x float]** + // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CBPADDR1]] + // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CPADDR1]] + // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* [[SADDR1]] + + // CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to float** + // CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to float** + // CHECK-DAG: store float* %{{.+}}, float** [[CBPADDR3]] + // CHECK-DAG: store float* %{{.+}}, float** [[CPADDR3]] + // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* [[SADDR3]] + + // CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to [5 x [10 x double]]** + // CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to [5 x [10 x double]]** + // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CBPADDR4]] + // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CPADDR4]] + // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* [[SADDR4]] + + // CHECK-DAG: [[CBPADDR7:%.+]] = bitcast i8** [[BPADDR7]] to double** + // CHECK-DAG: [[CPADDR7:%.+]] = bitcast i8** [[PADDR7]] to double** + // CHECK-DAG: store double* %{{.+}}, double** [[CBPADDR7]] + // CHECK-DAG: store double* %{{.+}}, double** [[CPADDR7]] + // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* [[SADDR7]] + + // CHECK-DAG: [[CBPADDR8:%.+]] = bitcast i8** [[BPADDR8]] to [[TT]]** + // CHECK-DAG: [[CPADDR8:%.+]] = bitcast i8** [[PADDR8]] to [[TT]]** + // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CBPADDR8]] + // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CPADDR8]] + // CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* [[SADDR8]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4 @@ -468,48 +470,53 @@ int bar(int n){ // CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 // CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 // CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX4]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. -// CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* -// CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* -// CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}} -// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - -// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}} -// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}} -// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - -// CHECK-DAG: [[BP2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8* -// CHECK-DAG: [[P2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8* -// CHECK-DAG: store i8* [[BP2]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P2]], i8** {{%[^,]+}} -// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} - -// CHECK-DAG: [[BP3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8* -// CHECK-DAG: [[P3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8* -// CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}} -// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} - -// CHECK-DAG: [[BP4:%[^,]+]] = bitcast i16* %{{.+}} to i8* -// CHECK-DAG: [[P4:%[^,]+]] = bitcast i16* %{{.+}} to i8* -// CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}} -// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} +// CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR3]] +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR3]] +// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR3]] + +// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR2]] +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR2]] +// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR2]] + +// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR1]] +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR1]] +// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR1]] + +// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to [[S1]]** +// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to [[S1]]** +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR0]] +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR0]] +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* [[SADDR0]] + +// CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to i16** +// CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to i16** +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4]] +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4]] +// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* [[SADDR4]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4 @@ -533,29 +540,31 @@ int bar(int n){ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 0 -// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] -// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] -// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8* -// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8* +// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL0:%[^,]+]], i[[SZ]]* [[CBPADDR0]] +// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]] // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 1 -// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] -// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] -// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8* -// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8* +// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL1:%[^,]+]], i[[SZ]]* [[CBPADDR1]] +// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]] // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 2 // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 2 -// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]] -// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]] +// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL2:%[^,]+]], i[[SZ]]* [[CBPADDR2]] +// CHECK-DAG: store i[[SZ]] [[VAL2]], i[[SZ]]* [[CPADDR2]] // CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 3 // CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 3 -// CHECK-DAG: store i8* [[BP3:%[^,]+]], i8** [[BPADDR3]] -// CHECK-DAG: store i8* [[P3:%[^,]+]], i8** [[PADDR3]] -// CHECK-DAG: [[BP3]] = bitcast [10 x i32]* %{{.+}} to i8* -// CHECK-DAG: [[P3]] = bitcast [10 x i32]* %{{.+}} to i8* +// CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to [10 x i32]** +// CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to [10 x i32]** +// CHECK-DAG: store [10 x i32]* [[VAL3:%[^,]+]], [10 x i32]** [[CBPADDR3]] +// CHECK-DAG: store [10 x i32]* [[VAL3]], [10 x i32]** [[CPADDR3]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] @@ -585,24 +594,24 @@ int bar(int n){ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 0 -// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] -// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] -// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8* -// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8* +// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL0:%[^,]+]], i[[SZ]]* [[CBPADDR0]] +// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]] // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 1 -// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] -// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] -// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8* -// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8* +// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL1:%[^,]+]], i[[SZ]]* [[CBPADDR1]] +// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]] // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 2 // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 2 -// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]] -// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]] -// CHECK-DAG: [[BP2]] = bitcast [10 x i32]* %{{.+}} to i8* -// CHECK-DAG: [[P2]] = bitcast [10 x i32]* %{{.+}} to i8* +// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to [10 x i32]** +// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to [10 x i32]** +// CHECK-DAG: store [10 x i32]* [[VAL2:%[^,]+]], [10 x i32]** [[CBPADDR2]] +// CHECK-DAG: store [10 x i32]* [[VAL2]], [10 x i32]** [[CPADDR2]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] diff --git a/test/OpenMP/target_codegen_global_capture.cpp b/test/OpenMP/target_codegen_global_capture.cpp index b08bf10f9f29..eb34082b2940 100644 --- a/test/OpenMP/target_codegen_global_capture.cpp +++ b/test/OpenMP/target_codegen_global_capture.cpp @@ -36,10 +36,10 @@ double Gd = 4.0; // CHECK-SAME: i16 {{[^,]*}}[[B:%[^,]+]], // CHECK-SAME: i16 {{[^,]*}}[[C:%[^,]+]], // CHECK-SAME: i16 {{[^,]*}}[[D:%[^,]+]]) -// CHECK: [[LA:%.+]] = alloca i16 -// CHECK: [[LB:%.+]] = alloca i16 -// CHECK: [[LC:%.+]] = alloca i16 -// CHECK: [[LD:%.+]] = alloca i16 +// CHECK: [[LA:%.+]] = alloca i16, +// CHECK: [[LB:%.+]] = alloca i16, +// CHECK: [[LC:%.+]] = alloca i16, +// CHECK: [[LD:%.+]] = alloca i16, int foo(short a, short b, short c, short d){ static float Sa = 5.0; static float Sb = 6.0; @@ -61,22 +61,22 @@ int foo(short a, short b, short c, short d){ // CHECK-DAG: store i16 [[VALLB]], i16* [[CONVLB:%.+]], // CHECK-DAG: [[CONVLB]] = bitcast i[[sz:64|32]]* [[CADDRLB:%.+]] to i16* // CHECK-DAG: [[CVALLB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLB]], - // CHECK-DAG: [[CPTRLB:%.+]] = inttoptr i[[sz]] [[CVALLB]] to i8* - // CHECK-DAG: store i8* [[CPTRLB]], i8** [[GEPLB:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLB]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLB:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store i16 [[VALLC]], i16* [[CONVLC:%.+]], // CHECK-DAG: [[CONVLC]] = bitcast i[[sz]]* [[CADDRLC:%.+]] to i16* // CHECK-DAG: [[CVALLC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLC]], - // CHECK-DAG: [[CPTRLC:%.+]] = inttoptr i[[sz]] [[CVALLC]] to i8* - // CHECK-DAG: store i8* [[CPTRLC]], i8** [[GEPLC:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLC]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLC:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store i16 [[VALLD]], i16* [[CONVLD:%.+]], // CHECK-DAG: [[CONVLD]] = bitcast i[[sz]]* [[CADDRLD:%.+]] to i16* // CHECK-DAG: [[CVALLD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLD]], - // CHECK-DAG: [[CPTRLD:%.+]] = inttoptr i[[sz]] [[CVALLD]] to i8* - // CHECK-DAG: store i8* [[CPTRLD]], i8** [[GEPLD:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLD]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLD:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // 3 static vars being captured. @@ -84,22 +84,22 @@ int foo(short a, short b, short c, short d){ // CHECK-DAG: store float [[VALFB]], float* [[CONVFB:%.+]], // CHECK-DAG: [[CONVFB]] = bitcast i[[sz]]* [[CADDRFB:%.+]] to float* // CHECK-DAG: [[CVALFB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFB]], - // CHECK-DAG: [[CPTRFB:%.+]] = inttoptr i[[sz]] [[CVALFB]] to i8* - // CHECK-DAG: store i8* [[CPTRFB]], i8** [[GEPFB:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFB]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFB:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store float [[VALFC]], float* [[CONVFC:%.+]], // CHECK-DAG: [[CONVFC]] = bitcast i[[sz]]* [[CADDRFC:%.+]] to float* // CHECK-DAG: [[CVALFC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFC]], - // CHECK-DAG: [[CPTRFC:%.+]] = inttoptr i[[sz]] [[CVALFC]] to i8* - // CHECK-DAG: store i8* [[CPTRFC]], i8** [[GEPFC:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFC]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFC:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store float [[VALFD]], float* [[CONVFD:%.+]], // CHECK-DAG: [[CONVFD]] = bitcast i[[sz]]* [[CADDRFD:%.+]] to float* // CHECK-DAG: [[CVALFD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFD]], - // CHECK-DAG: [[CPTRFD:%.+]] = inttoptr i[[sz]] [[CVALFD]] to i8* - // CHECK-DAG: store i8* [[CPTRFD]], i8** [[GEPFD:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFD]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFD:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // 3 static global vars being captured. @@ -107,25 +107,28 @@ int foo(short a, short b, short c, short d){ // CHECK-64-DAG: store double [[VALGB]], double* [[CONVGB:%.+]], // CHECK-64-DAG: [[CONVGB]] = bitcast i[[sz]]* [[CADDRGB:%.+]] to double* // CHECK-64-DAG: [[CVALGB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGB]], - // CHECK-64-DAG: [[CPTRGB:%.+]] = inttoptr i[[sz]] [[CVALGB]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGB]], i8** [[GEPGB:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gb to i8*), i8** [[GEPGB:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGB]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gb, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to double** // CHECK-DAG: [[GEPGB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-64-DAG: store double [[VALGC]], double* [[CONVGC:%.+]], // CHECK-64-DAG: [[CONVGC]] = bitcast i[[sz]]* [[CADDRGC:%.+]] to double* // CHECK-64-DAG: [[CVALGC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGC]], - // CHECK-64-DAG: [[CPTRGC:%.+]] = inttoptr i[[sz]] [[CVALGC]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGC]], i8** [[GEPGC:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gc to i8*), i8** [[GEPGC:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGC]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gc, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to double** // CHECK-DAG: [[GEPGC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-64-DAG: store double [[VALGD]], double* [[CONVGD:%.+]], // CHECK-64-DAG: [[CONVGD]] = bitcast i[[sz]]* [[CADDRGD:%.+]] to double* // CHECK-64-DAG: [[CVALGD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGD]], - // CHECK-64-DAG: [[CPTRGD:%.+]] = inttoptr i[[sz]] [[CVALGD]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGD]], i8** [[GEPGD:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gd to i8*), i8** [[GEPGD:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGD]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gd, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to double** // CHECK-DAG: [[GEPGD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK: call i32 @__tgt_target @@ -197,22 +200,22 @@ int bar(short a, short b, short c, short d){ // CHECK-DAG: store i16 [[VALLB]], i16* [[CONVLB:%.+]], // CHECK-DAG: [[CONVLB]] = bitcast i[[sz:64|32]]* [[CADDRLB:%.+]] to i16* // CHECK-DAG: [[CVALLB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLB]], - // CHECK-DAG: [[CPTRLB:%.+]] = inttoptr i[[sz]] [[CVALLB]] to i8* - // CHECK-DAG: store i8* [[CPTRLB]], i8** [[GEPLB:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLB]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLB:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store i16 [[VALLC]], i16* [[CONVLC:%.+]], // CHECK-DAG: [[CONVLC]] = bitcast i[[sz]]* [[CADDRLC:%.+]] to i16* // CHECK-DAG: [[CVALLC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLC]], - // CHECK-DAG: [[CPTRLC:%.+]] = inttoptr i[[sz]] [[CVALLC]] to i8* - // CHECK-DAG: store i8* [[CPTRLC]], i8** [[GEPLC:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLC]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLC:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store i16 [[VALLD]], i16* [[CONVLD:%.+]], // CHECK-DAG: [[CONVLD]] = bitcast i[[sz]]* [[CADDRLD:%.+]] to i16* // CHECK-DAG: [[CVALLD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLD]], - // CHECK-DAG: [[CPTRLD:%.+]] = inttoptr i[[sz]] [[CVALLD]] to i8* - // CHECK-DAG: store i8* [[CPTRLD]], i8** [[GEPLD:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLD]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLD:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // 3 static vars being captured. @@ -220,22 +223,22 @@ int bar(short a, short b, short c, short d){ // CHECK-DAG: store float [[VALFB]], float* [[CONVFB:%.+]], // CHECK-DAG: [[CONVFB]] = bitcast i[[sz]]* [[CADDRFB:%.+]] to float* // CHECK-DAG: [[CVALFB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFB]], - // CHECK-DAG: [[CPTRFB:%.+]] = inttoptr i[[sz]] [[CVALFB]] to i8* - // CHECK-DAG: store i8* [[CPTRFB]], i8** [[GEPFB:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFB]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFB:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store float [[VALFC]], float* [[CONVFC:%.+]], // CHECK-DAG: [[CONVFC]] = bitcast i[[sz]]* [[CADDRFC:%.+]] to float* // CHECK-DAG: [[CVALFC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFC]], - // CHECK-DAG: [[CPTRFC:%.+]] = inttoptr i[[sz]] [[CVALFC]] to i8* - // CHECK-DAG: store i8* [[CPTRFC]], i8** [[GEPFC:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFC]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFC:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store float [[VALFD]], float* [[CONVFD:%.+]], // CHECK-DAG: [[CONVFD]] = bitcast i[[sz]]* [[CADDRFD:%.+]] to float* // CHECK-DAG: [[CVALFD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFD]], - // CHECK-DAG: [[CPTRFD:%.+]] = inttoptr i[[sz]] [[CVALFD]] to i8* - // CHECK-DAG: store i8* [[CPTRFD]], i8** [[GEPFD:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFD]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFD:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // 3 static global vars being captured. @@ -243,25 +246,28 @@ int bar(short a, short b, short c, short d){ // CHECK-64-DAG: store double [[VALGB]], double* [[CONVGB:%.+]], // CHECK-64-DAG: [[CONVGB]] = bitcast i[[sz]]* [[CADDRGB:%.+]] to double* // CHECK-64-DAG: [[CVALGB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGB]], - // CHECK-64-DAG: [[CPTRGB:%.+]] = inttoptr i[[sz]] [[CVALGB]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGB]], i8** [[GEPGB:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gb to i8*), i8** [[GEPGB:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGB]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gb, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to double** // CHECK-DAG: [[GEPGB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-64-DAG: store double [[VALGC]], double* [[CONVGC:%.+]], // CHECK-64-DAG: [[CONVGC]] = bitcast i[[sz]]* [[CADDRGC:%.+]] to double* // CHECK-64-DAG: [[CVALGC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGC]], - // CHECK-64-DAG: [[CPTRGC:%.+]] = inttoptr i[[sz]] [[CVALGC]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGC]], i8** [[GEPGC:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gc to i8*), i8** [[GEPGC:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGC]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gc, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to double** // CHECK-DAG: [[GEPGC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-64-DAG: store double [[VALGD]], double* [[CONVGD:%.+]], // CHECK-64-DAG: [[CONVGD]] = bitcast i[[sz]]* [[CADDRGD:%.+]] to double* // CHECK-64-DAG: [[CVALGD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGD]], - // CHECK-64-DAG: [[CPTRGD:%.+]] = inttoptr i[[sz]] [[CVALGD]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGD]], i8** [[GEPGD:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gd to i8*), i8** [[GEPGD:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGD]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gd, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to double** // CHECK-DAG: [[GEPGD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK: call i32 @__tgt_target @@ -339,22 +345,22 @@ int tbar(T a, T b, T c, T d){ // CHECK-DAG: store i16 [[VALLB]], i16* [[CONVLB:%.+]], // CHECK-DAG: [[CONVLB]] = bitcast i[[sz:64|32]]* [[CADDRLB:%.+]] to i16* // CHECK-DAG: [[CVALLB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLB]], - // CHECK-DAG: [[CPTRLB:%.+]] = inttoptr i[[sz]] [[CVALLB]] to i8* - // CHECK-DAG: store i8* [[CPTRLB]], i8** [[GEPLB:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLB]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLB:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store i16 [[VALLC]], i16* [[CONVLC:%.+]], // CHECK-DAG: [[CONVLC]] = bitcast i[[sz]]* [[CADDRLC:%.+]] to i16* // CHECK-DAG: [[CVALLC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLC]], - // CHECK-DAG: [[CPTRLC:%.+]] = inttoptr i[[sz]] [[CVALLC]] to i8* - // CHECK-DAG: store i8* [[CPTRLC]], i8** [[GEPLC:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLC]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLC:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store i16 [[VALLD]], i16* [[CONVLD:%.+]], // CHECK-DAG: [[CONVLD]] = bitcast i[[sz]]* [[CADDRLD:%.+]] to i16* // CHECK-DAG: [[CVALLD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRLD]], - // CHECK-DAG: [[CPTRLD:%.+]] = inttoptr i[[sz]] [[CVALLD]] to i8* - // CHECK-DAG: store i8* [[CPTRLD]], i8** [[GEPLD:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALLD]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPLD:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPLD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // 3 static vars being captured. @@ -362,22 +368,22 @@ int tbar(T a, T b, T c, T d){ // CHECK-DAG: store float [[VALFB]], float* [[CONVFB:%.+]], // CHECK-DAG: [[CONVFB]] = bitcast i[[sz]]* [[CADDRFB:%.+]] to float* // CHECK-DAG: [[CVALFB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFB]], - // CHECK-DAG: [[CPTRFB:%.+]] = inttoptr i[[sz]] [[CVALFB]] to i8* - // CHECK-DAG: store i8* [[CPTRFB]], i8** [[GEPFB:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFB]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFB:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store float [[VALFC]], float* [[CONVFC:%.+]], // CHECK-DAG: [[CONVFC]] = bitcast i[[sz]]* [[CADDRFC:%.+]] to float* // CHECK-DAG: [[CVALFC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFC]], - // CHECK-DAG: [[CPTRFC:%.+]] = inttoptr i[[sz]] [[CVALFC]] to i8* - // CHECK-DAG: store i8* [[CPTRFC]], i8** [[GEPFC:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFC]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFC:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-DAG: store float [[VALFD]], float* [[CONVFD:%.+]], // CHECK-DAG: [[CONVFD]] = bitcast i[[sz]]* [[CADDRFD:%.+]] to float* // CHECK-DAG: [[CVALFD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRFD]], - // CHECK-DAG: [[CPTRFD:%.+]] = inttoptr i[[sz]] [[CVALFD]] to i8* - // CHECK-DAG: store i8* [[CPTRFD]], i8** [[GEPFD:%.+]], + // CHECK-DAG: store i[[sz]] [[CVALFD]], i[[sz]]* [[CBP:%.+]], + // CHECK-DAG: [[CBP]] = bitcast i8** [[GEPFD:%.+]] to i[[sz]]* // CHECK-DAG: [[GEPFD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // 3 static global vars being captured. @@ -385,25 +391,28 @@ int tbar(T a, T b, T c, T d){ // CHECK-64-DAG: store double [[VALGB]], double* [[CONVGB:%.+]], // CHECK-64-DAG: [[CONVGB]] = bitcast i[[sz]]* [[CADDRGB:%.+]] to double* // CHECK-64-DAG: [[CVALGB:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGB]], - // CHECK-64-DAG: [[CPTRGB:%.+]] = inttoptr i[[sz]] [[CVALGB]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGB]], i8** [[GEPGB:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gb to i8*), i8** [[GEPGB:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGB]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gb, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGB:%.+]] to double** // CHECK-DAG: [[GEPGB]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-64-DAG: store double [[VALGC]], double* [[CONVGC:%.+]], // CHECK-64-DAG: [[CONVGC]] = bitcast i[[sz]]* [[CADDRGC:%.+]] to double* // CHECK-64-DAG: [[CVALGC:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGC]], - // CHECK-64-DAG: [[CPTRGC:%.+]] = inttoptr i[[sz]] [[CVALGC]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGC]], i8** [[GEPGC:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gc to i8*), i8** [[GEPGC:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGC]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gc, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGC:%.+]] to double** // CHECK-DAG: [[GEPGC]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK-64-DAG: store double [[VALGD]], double* [[CONVGD:%.+]], // CHECK-64-DAG: [[CONVGD]] = bitcast i[[sz]]* [[CADDRGD:%.+]] to double* // CHECK-64-DAG: [[CVALGD:%.+]] = load i[[sz]], i[[sz]]* [[CADDRGD]], - // CHECK-64-DAG: [[CPTRGD:%.+]] = inttoptr i[[sz]] [[CVALGD]] to i8* - // CHECK-64-DAG: store i8* [[CPTRGD]], i8** [[GEPGD:%.+]], - // CHECK-32-DAG: store i8* bitcast (double* @Gd to i8*), i8** [[GEPGD:%.+]], + // CHECK-64-DAG: store i[[sz]] [[CVALGD]], i[[sz]]* [[CBP:%.+]], + // CHECK-64-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to i[[sz]]* + // CHECK-32-DAG: store double* @Gd, double** [[CBP:%.+]], + // CHECK-32-DAG: [[CBP]] = bitcast i8** [[GEPGD:%.+]] to double** // CHECK-DAG: [[GEPGD]] = getelementptr inbounds [9 x i8*], [9 x i8*]* %{{.+}}, i32 0, i32 {{[0-8]}} // CHECK: call i32 @__tgt_target diff --git a/test/OpenMP/target_data_codegen.cpp b/test/OpenMP/target_data_codegen.cpp index a149ba9332b9..7e5e267d13b6 100644 --- a/test/OpenMP/target_data_codegen.cpp +++ b/test/OpenMP/target_data_codegen.cpp @@ -45,8 +45,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x double]** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x double]** + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CBP0]] + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CP0]] // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 @@ -71,10 +73,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK1-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK1-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK1: br label %[[IFEND:[^,]+]] // CK1: [[IFELSE]] @@ -103,11 +105,11 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK1-DAG: store float* [[VAR0:%.+]], float** [[CBP0]] + // CK1-DAG: store float* [[VAR0]], float** [[CP0]] // CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]] - // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8* // CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4 // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 @@ -128,15 +130,18 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** + // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]] + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]] // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]] - // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]] + // CK1-DAG: store double* [[SEC1:%.+]], double** [[CP1]] // CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0 // CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), @@ -191,19 +196,19 @@ int bar(int arg){ // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* -// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8* +// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** +// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** +// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] +// CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8* -// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8* +// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** +// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** +// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]] +// CK2-DAG: store double* [[SEC1:%.+]], double** [[CP1]] // CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1 // CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]], // CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 diff --git a/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/test/OpenMP/target_data_use_device_ptr_codegen.cpp index c4b389a4cbb8..5e275565170e 100644 --- a/test/OpenMP/target_data_use_device_ptr_codegen.cpp +++ b/test/OpenMP/target_data_use_device_ptr_codegen.cpp @@ -33,12 +33,11 @@ void foo(float *&lr, T *&tr) { float *l; T *t; - // CK1-DAG: [[RVAL:%.+]] = bitcast double* [[T:%.+]] to i8* - // CK1-DAG: [[T]] = load double*, double** [[DECL:@g]], + // CK1: [[T:%.+]] = load double*, double** [[DECL:@g]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to double** + // CK1: store double* [[T]], double** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]] // CK1: [[VAL:%.+]] = load double*, double** [[CBP]], // CK1-NOT: store double* [[VAL]], double** [[DECL]], // CK1: store double* [[VAL]], double** [[PVT:%.+]], @@ -53,12 +52,11 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds double, double* [[TTT]], i32 1 ++g; - // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float** + // CK1: store float* [[T1]], float** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]] // CK1: [[VAL:%.+]] = load float*, float** [[CBP]], // CK1-NOT: store float* [[VAL]], float** [[DECL]], // CK1: store float* [[VAL]], float** [[PVT:%.+]], @@ -85,12 +83,11 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds float, float* [[TTT]], i32 1 ++l; - // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float** + // CK1: store float* [[T1]], float** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]] // CK1: [[VAL:%.+]] = load float*, float** [[CBP]], // CK1-NOT: store float* [[VAL]], float** [[DECL]], // CK1: store float* [[VAL]], float** [[PVT:%.+]], @@ -109,12 +106,11 @@ void foo(float *&lr, T *&tr) { // CK1: br i1 [[CMP]], label %[[BTHEN:.+]], label %[[BELSE:.+]] // CK1: [[BTHEN]]: - // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE04]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float** + // CK1: store float* [[T1]], float** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE04]] // CK1: [[VAL:%.+]] = load float*, float** [[CBP]], // CK1-NOT: store float* [[VAL]], float** [[DECL]], // CK1: store float* [[VAL]], float** [[PVT:%.+]], @@ -146,13 +142,12 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds float, float* [[TTT]], i32 1 ++l; - // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load float*, float** [[T2:%.+]], - // CK1-DAG: [[T2]] = load float**, float*** [[DECL:%.+]], + // CK1: [[T2:%.+]] = load float**, float*** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load float*, float** [[T2]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE05]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float** + // CK1: store float* [[T1]], float** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE05]] // CK1: [[VAL:%.+]] = load float*, float** [[CBP]], // CK1: store float* [[VAL]], float** [[PVTV:%.+]], // CK1-NOT: store float** [[PVTV]], float*** [[DECL]], @@ -170,12 +165,11 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds float, float* [[TTTT]], i32 1 ++lr; - // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load i32*, i32** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load i32*, i32** [[DECL:%.+]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE06]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32** + // CK1: store i32* [[T1]], i32** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE06]] // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]], // CK1-NOT: store i32* [[VAL]], i32** [[DECL]], // CK1: store i32* [[VAL]], i32** [[PVT:%.+]], @@ -190,13 +184,12 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1 ++t; - // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load i32*, i32** [[T2:%.+]], - // CK1-DAG: [[T2]] = load i32**, i32*** [[DECL:%.+]], + // CK1: [[T2:%.+]] = load i32**, i32*** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load i32*, i32** [[T2]], // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE07]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32** + // CK1: store i32* [[T1]], i32** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE07]] // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]], // CK1: store i32* [[VAL]], i32** [[PVTV:%.+]], // CK1-NOT: store i32** [[PVTV]], i32*** [[DECL]], @@ -214,12 +207,11 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds i32, i32* [[TTTT]], i32 1 ++tr; - // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load float*, float** [[DECL:%.+]], // CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE08]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float** + // CK1: store float* [[T1]], float** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE08]] // CK1: [[VAL:%.+]] = load float*, float** [[CBP]], // CK1-NOT: store float* [[VAL]], float** [[DECL]], // CK1: store float* [[VAL]], float** [[PVT:%.+]], @@ -235,11 +227,11 @@ void foo(float *&lr, T *&tr) { ++l; ++t; - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE09]] // CK1: [[_CBP:%.+]] = bitcast i8** {{%.+}} to float** + // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32** + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE09]] // CK1: [[_VAL:%.+]] = load float*, float** [[_CBP]], // CK1: store float* [[_VAL]], float** [[_PVT:%.+]], - // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32** // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]], // CK1: store i32* [[VAL]], i32** [[PVT:%.+]], // CK1: [[_TT1:%.+]] = load float*, float** [[_PVT]], @@ -257,11 +249,11 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1 ++l; ++t; - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE10]] // CK1: [[_CBP:%.+]] = bitcast i8** {{%.+}} to float** + // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32** + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE10]] // CK1: [[_VAL:%.+]] = load float*, float** [[_CBP]], // CK1: store float* [[_VAL]], float** [[_PVT:%.+]], - // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32** // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]], // CK1: store i32* [[VAL]], i32** [[PVT:%.+]], // CK1: [[_TT1:%.+]] = load float*, float** [[_PVT]], @@ -279,12 +271,11 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1 ++l; ++t; - // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load i32*, i32** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load i32*, i32** [[DECL:%.+]], // CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE11]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32** + // CK1: store i32* [[T1]], i32** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE11]] // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]], // CK1-NOT: store i32* [[VAL]], i32** [[DECL]], // CK1: store i32* [[VAL]], i32** [[PVT:%.+]], @@ -299,13 +290,12 @@ void foo(float *&lr, T *&tr) { // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1 ++l; ++t; - // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8* - // CK1-DAG: [[T1]] = load i32*, i32** [[T2:%.+]], - // CK1-DAG: [[T2]] = load i32**, i32*** [[DECL:%.+]], + // CK1: [[T2:%.+]] = load i32**, i32*** [[DECL:%.+]], + // CK1: [[T1:%.+]] = load i32*, i32** [[T2]], // CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0 - // CK1: store i8* [[RVAL]], i8** [[BP]], - // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE12]] // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32** + // CK1: store i32* [[T1]], i32** [[CBP]], + // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE12]] // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]], // CK1: store i32* [[VAL]], i32** [[PVTV:%.+]], // CK1-NOT: store i32** [[PVTV]], i32*** [[DECL]], @@ -356,10 +346,11 @@ struct ST { int *la = 0; // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 1 - // CK2: store i8* [[RVAL:%.+]], i8** [[BP]], + // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double*** + // CK2: store double** [[RVAL:%.+]], double*** [[CBP]], // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]] - // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** - // CK2: [[VAL:%.+]] = load double*, double** [[CBP]], + // CK2: [[CBP1:%.+]] = bitcast double*** [[CBP]] to double** + // CK2: [[VAL:%.+]] = load double*, double** [[CBP1]], // CK2: store double* [[VAL]], double** [[PVT:%.+]], // CK2: store double** [[PVT]], double*** [[PVT2:%.+]], // CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]], @@ -376,10 +367,11 @@ struct ST { a++; // CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2 - // CK2: store i8* [[RVAL:%.+]], i8** [[BP]], + // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double*** + // CK2: store double** [[RVAL:%.+]], double*** [[CBP]], // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]] - // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** - // CK2: [[VAL:%.+]] = load double*, double** [[CBP]], + // CK2: [[CBP1:%.+]] = bitcast double*** [[CBP]] to double** + // CK2: [[VAL:%.+]] = load double*, double** [[CBP1]], // CK2: store double* [[VAL]], double** [[PVT:%.+]], // CK2: store double** [[PVT]], double*** [[PVT2:%.+]], // CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]], @@ -397,9 +389,9 @@ struct ST { b++; // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0 - // CK2: store i8* [[RVAL:%.+]], i8** [[BP]], - // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]] // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** + // CK2: store double* [[RVAL:%.+]], double** [[CBP]], + // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]] // CK2: [[VAL:%.+]] = load double*, double** [[CBP]], // CK2: store double* [[VAL]], double** [[PVT:%.+]], // CK2: store double** [[PVT]], double*** [[PVT2:%.+]], @@ -419,16 +411,17 @@ struct ST { la++; // CK2: [[BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 0 - // CK2: store i8* [[RVAL:%.+]], i8** [[BP]], + // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** + // CK2: store double* [[RVAL:%.+]], double** [[CBP]], // CK2: [[_BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 3 - // CK2: store i8* [[_RVAL:%.+]], i8** [[_BP]], + // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double*** + // CK2: store double** [[_RVAL:%.+]], double*** [[_CBP]], // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]] - // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** // CK2: [[VAL:%.+]] = load double*, double** [[CBP]], // CK2: store double* [[VAL]], double** [[PVT:%.+]], // CK2: store double** [[PVT]], double*** [[PVT2:%.+]], - // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double** - // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP]], + // CK2: [[_CBP1:%.+]] = bitcast double*** [[_CBP]] to double** + // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP1]], // CK2: store double* [[_VAL]], double** [[_PVT:%.+]], // CK2: store double** [[_PVT]], double*** [[_PVT2:%.+]], // CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]], diff --git a/test/OpenMP/target_enter_data_codegen.cpp b/test/OpenMP/target_enter_data_codegen.cpp index 152cd46b4a2f..683cd976d395 100644 --- a/test/OpenMP/target_enter_data_codegen.cpp +++ b/test/OpenMP/target_enter_data_codegen.cpp @@ -45,8 +45,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x double]** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x double]** + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CBP0]] + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[CP0]] // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 // CK1-NOT: __tgt_target_data_end @@ -67,10 +69,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK1-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK1-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK1: br label %[[IFEND:[^,]+]] // CK1: [[IFELSE]] @@ -93,11 +95,11 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK1-DAG: store float* [[VAR0:%.+]], float** [[CBP0]] + // CK1-DAG: store float* [[VAR0]], float** [[CP0]] // CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]] - // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8* // CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4 // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 // CK1-NOT: __tgt_target_data_end @@ -114,15 +116,18 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** + // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]] + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]] // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]] - // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]] + // CK1-DAG: store double* [[SEC1:%.+]], double** [[CP1]] // CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0 // CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), @@ -174,19 +179,19 @@ int bar(int arg){ // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* -// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8* +// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** +// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** +// CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] +// CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8* -// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8* +// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** +// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** +// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]] +// CK2-DAG: store double* [[SEC1:%.+]], double** [[CP1]] // CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1 // CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]], // CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 diff --git a/test/OpenMP/target_exit_data_codegen.cpp b/test/OpenMP/target_exit_data_codegen.cpp index d3a38592a610..a82c1c6c4aac 100644 --- a/test/OpenMP/target_exit_data_codegen.cpp +++ b/test/OpenMP/target_exit_data_codegen.cpp @@ -46,8 +46,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]] + // CK1-DAG: [[BPC0:%.+]] = bitcast i8** [[BP0]] to [100 x double]** + // CK1-DAG: [[PC0:%.+]] = bitcast i8** [[P0]] to [100 x double]** + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[BPC0]] + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[PC0]] // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 #pragma omp target exit data if(1+3-5) device(arg) map(from: gc) @@ -68,10 +70,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK1-DAG: store i32* [[VAL0:%[^,]+]], i32** [[CBP0]] + // CK1-DAG: store i32* [[VAL0]], i32** [[CP0]] // CK1: br label %[[IFEND:[^,]+]] // CK1: [[IFELSE]] @@ -94,11 +96,11 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK1-DAG: store float* [[VAL0:%[^,]+]], float** [[CBP0]] + // CK1-DAG: store float* [[VAL0]], float** [[CP0]] // CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]] - // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8* // CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4 // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 #pragma omp target exit data map(always, from: lb) @@ -115,15 +117,18 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** + // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]] + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]] // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]] - // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]] + // CK1-DAG: store double* [[SEC1:%[^,]+]], double** [[CP1]] // CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0 // CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), @@ -175,19 +180,19 @@ int bar(int arg){ // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* -// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8* +// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** +// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** +// CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]] +// CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8* -// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8* +// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** +// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** +// CK2-DAG: store double** [[SEC0]], double*** [[CBP1]] +// CK2-DAG: store double* [[SEC1:%[^,]+]], double** [[CP1]] // CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1 // CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]], // CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 diff --git a/test/OpenMP/target_firstprivate_codegen.cpp b/test/OpenMP/target_firstprivate_codegen.cpp index a9af2d02f237..1fb0ef9e848c 100644 --- a/test/OpenMP/target_firstprivate_codegen.cpp +++ b/test/OpenMP/target_firstprivate_codegen.cpp @@ -93,12 +93,12 @@ int foo(int n, double *ptr) { // CHECK-64: store i{{[0-9]+}} [[AVAL]], i{{[0-9]+}}* [[CONV]], // CHECK-32: store i{{[0-9]+}} [[AVAL]], i{{[0-9]+}}* [[ACAST]], // CHECK: [[ACAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ACAST]], - // CHECK: [[ACAST_TOPTR:%.+]] = inttoptr i{{[0-9]+}} [[ACAST_VAL]] to i8* // CHECK: [[BASE_PTR_GEP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[ACAST_TOPTR]], i8** [[BASE_PTR_GEP]], - // CHECK: [[ACAST_TOPTR2:%.+]] = inttoptr i{{[0-9]+}} [[ACAST_VAL]] to i8* + // CHECK: [[ACAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[ACAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR]], // CHECK: [[PTR_GEP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[ACAST_TOPTR2]], i8** [[PTR_GEP]], + // CHECK: [[ACAST_TOPTR2:%.+]] = bitcast i8** [[PTR_GEP]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[ACAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR2]], // CHECK: [[BASE_PTR_GEP_ARG:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 // CHECK: [[PTR_GEP_ARG:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 // CHECK: {{.+}} = call i32 @__tgt_target(i32 -1, {{.+}}, i32 1, i8** [[BASE_PTR_GEP_ARG]], i8** [[PTR_GEP_ARG]], i[[SZ]]* getelementptr inbounds ([1 x i[[SZ]]], [1 x i[[SZ]]]* [[SIZET]], i32 0, i32 0), i32* getelementptr inbounds ([1 x i32], [1 x i32]* [[MAPT]], i32 0, i32 0)) @@ -132,85 +132,87 @@ int foo(int n, double *ptr) { // CHECK: [[CN_SIZE_2:%.+]] = mul{{.+}} i{{[0-9]+}} [[CN_SIZE_1]], 8 // firstprivate(aa) --> base_ptr = aa, ptr = aa, size = 2 (short) - // CHECK: [[A2CAST_TO_INT:%.+]] = inttoptr i{{[0-9]+}} [[A2CAST_VAL]] to i8* // CHECK: [[BASE_PTR_GEP2_0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[A2CAST_TO_INT]], i8** [[BASE_PTR_GEP2_0]], - // CHECK: [[A2CAST_TO_INT_2:%.+]] = inttoptr i{{[0-9]+}} [[A2CAST_VAL]] to i8* + // CHECK: [[ACAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_0]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[A2CAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR]], // CHECK: [[PTR_GEP2_0:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[A2CAST_TO_INT_2]], i8** [[PTR_GEP2_0]], + // CHECK: [[ACAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_0]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[A2CAST_VAL]], i{{[0-9]+}}* [[ACAST_TOPTR]], // CHECK: [[SIZE_GEPA2:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 // CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[SIZE_GEPA2]], // firstprivate(b): base_ptr = &b[0], ptr = &b[0], size = 40 (sizeof(float)*10) - // CHECK: [[BCAST:%.+]] = bitcast [10 x float]* [[B]] to i8* // CHECK: [[BASE_PTR_GEP2_1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // CHECK: store i8* [[BCAST]], i8** [[BASE_PTR_GEP2_1]], - // CHECK: [[BCAST2:%.+]] = bitcast [10 x float]* [[B]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_1]] to [10 x float]** + // CHECK: store [10 x float]* [[B]], [10 x float]** [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_1:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // CHECK: store i8* [[BCAST2]], i8** [[PTR_GEP2_1]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_1]] to [10 x float]** + // CHECK: store [10 x float]* [[B]], [10 x float]** [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPB:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 // CHECK: store i{{[0-9]+}} 40, i{{[0-9]+}}* [[SIZE_GEPB]], // firstprivate(bn), 2 entries, n and bn: (1) base_ptr = n, ptr = n, size = 8 ; (2) base_ptr = &c[0], ptr = &c[0], size = n*sizeof(float) - // CHECK-64: [[N_EXT3_1:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT]] to i8* - // CHECK-32: [[N_EXT3_1:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL]] to i8* // CHECK: [[BASE_PTR_GEP2_2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // CHECK: store i8* [[N_EXT3_1]], i8** [[BASE_PTR_GEP2_2]], - // CHECK-64: [[N_EXT3_2:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT]] to i8* - // CHECK-32: [[N_EXT3_2:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_2]] to i{{[0-9]+}}* + // CHECK-64: store i{{[0-9]+}} [[N_EXT]], i{{[0-9]+}}* [[BCAST_TOPTR]], + // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_2:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // CHECK: store i8* [[N_EXT3_2]], i8** [[PTR_GEP2_2]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_2]] to i{{[0-9]+}}* + // CHECK-64: store i{{[0-9]+}} [[N_EXT]], i{{[0-9]+}}* [[BCAST_TOPTR]], + // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPBN_1:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK: store i{{[0-9]+}} {{[0-9]}}, i{{[0-9]+}}* [[SIZE_GEPBN_1]], - // CHECK: [[VLABN_BCAST:%.+]] = bitcast float* [[BN_VLA]] to i8* // CHECK: [[BASE_PTR_GEP2_3:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 - // CHECK: store i8* [[VLABN_BCAST]], i8** [[BASE_PTR_GEP2_3]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_3]] to float** + // CHECK: store float* [[BN_VLA]], float** [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPBN_3:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 // CHECK: store i{{[0-9]+}} [[BN_SIZE]], i{{[0-9]+}}* [[SIZE_GEPBN_3]] // firstprivate(c): base_ptr = &c[0], ptr = &c[0], size = 400 (5*10*sizeof(double)) - // CHECK: [[C_BCAST:%.+]] = bitcast [5 x [10 x double]]* [[C]] to i8* // CHECK: [[BASE_PTR_GEP2_4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 - // CHECK: store i8* [[C_BCAST]], i8** [[BASE_PTR_GEP2_4]], - // CHECK: [[C_BCAST2:%.+]] = bitcast [5 x [10 x double]]* [[C]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_4]] to [5 x [10 x double]]** + // CHECK: store [5 x [10 x double]]* [[C]], [5 x [10 x double]]** [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_4:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 - // CHECK: store i8* [[C_BCAST2]], i8** [[PTR_GEP2_4]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_4]] to [5 x [10 x double]]** + // CHECK: store [5 x [10 x double]]* [[C]], [5 x [10 x double]]** [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPC_4:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 // CHECK: store i{{[0-9]+}} 400, i{{[0-9]+}}* [[SIZE_GEPC_4]], // firstprivate(cn), 3 entries, 5, n, cn: (1) base_ptr = 5, ptr = 5, size = 8; (2) (1) base_ptr = n, ptr = n, size = 8; (3) base_ptr = &cn[0], ptr = &cn[0], size = 5*n*sizeof(double) // CHECK: [[BASE_PTR_GEP2_5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 5 - // CHECK: store i8* inttoptr (i{{[0-9]+}} 5 to i8*), i8** [[BASE_PTR_GEP2_5]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_5]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} 5, i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_5:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 5 - // CHECK: store i8* inttoptr (i{{[0-9]+}} 5 to i8*), i8** [[PTR_GEP2_5]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_5]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} 5, i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPCN_5:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 5 // CHECK: store i{{[0-9]+}} {{[0-9]}}, i{{[0-9]+}}* [[SIZE_GEPCN_5]], - // CHECK-64: [[CN_SZ_2_1:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT2]] to i8* - // CHECK-32: [[CN_SZ_2_1:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL2]] to i8* // CHECK: [[BASE_PTR_GEP2_6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 6 - // CHECK: store i8* [[CN_SZ_2_1]], i8** [[BASE_PTR_GEP2_6]], - // CHECK-64: [[CN_SZ_2_2:%.+]] = inttoptr i{{[0-9]+}} [[N_EXT2]] to i8* - // CHECK-32: [[CN_SZ_2_2:%.+]] = inttoptr i{{[0-9]+}} [[N_ADDR_VAL2]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_6]] to i{{[0-9]+}}* + // CHECK-64: store i{{[0-9]+}} [[N_EXT2]], i{{[0-9]+}}* [[BCAST_TOPTR]], + // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL2]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_6:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 6 - // CHECK: store i8* [[CN_SZ_2_2]], i8** [[PTR_GEP2_6]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_6]] to i{{[0-9]+}}* + // CHECK-64: store i{{[0-9]+}} [[N_EXT2]], i{{[0-9]+}}* [[BCAST_TOPTR]], + // CHECK-32: store i{{[0-9]+}} [[N_ADDR_VAL2]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPCN_6:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 6 // CHECK: store i{{[0-9]+}} {{[0-9]}}, i{{[0-9]+}}* [[SIZE_GEPCN_6]], - // CHECK: [[VLA_CN_BCAST:%.+]] = bitcast double* [[CN_VLA]] to i8* // CHECK: [[BASE_PTR_GEP2_7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 7 - // CHECK: store i8* [[VLA_CN_BCAST]], i8** [[BASE_PTR_GEP2_7]], - // CHECK: [[VLA_CN_BCAST2:%.+]] = bitcast double* [[CN_VLA]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_7]] to double** + // CHECK: store double* [[CN_VLA]], double** [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_7:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 7 - // CHECK: store i8* [[VLA_CN_BCAST2]], i8** [[PTR_GEP2_7]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_7]] to double** + // CHECK: store double* [[CN_VLA]], double** [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPCN_7:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 7 // CHECK: store i{{[0-9]+}} [[CN_SIZE_2]], i{{[0-9]+}}* [[SIZE_GEPCN_7]], // firstprivate(d): base_ptr = &d, ptr = &d, size = 16 - // CHECK: [[D_REF:%.+]] = bitcast [[TT]]* [[D]] to i8* // CHECK: [[BASE_PTR_GEP2_8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[BASE_PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 8 - // CHECK: store i8* [[D_REF]], i8** [[BASE_PTR_GEP2_8]], - // CHECK: [[D_REF2:%.+]] = bitcast [[TT]]* [[D]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP2_8]] to [[TT]]** + // CHECK: store [[TT]]* [[D]], [[TT]]** [[BCAST_TOPTR]], // CHECK: [[PTR_GEP2_8:%.+]] = getelementptr inbounds [9 x i8*], [9 x i8*]* [[PTR_ARR2]], i{{[0-9]+}} 0, i{{[0-9]+}} 8 - // CHECK: store i8* [[D_REF2]], i8** [[PTR_GEP2_8]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP2_8]] to [[TT]]** + // CHECK: store [[TT]]* [[D]], [[TT]]** [[BCAST_TOPTR]], // CHECK: [[SIZE_GEPCN_8:%.+]] = getelementptr inbounds [9 x i{{[0-9]+}}], [9 x i{{[0-9]+}}]* [[SIZET2]], i{{[0-9]+}} 0, i{{[0-9]+}} 8 // CHECK: store i{{[0-9]+}} {{[0-9]+}}, i{{[0-9]+}}* [[SIZE_GEPCN_8]], @@ -299,13 +301,13 @@ int foo(int n, double *ptr) { ptr[0]++; } // CHECK: [[PTR_ADDR_REF:%.+]] = load double*, double** [[PTR_ADDR]], - // CHECK: [[PTR_ADDR_BCAST:%.+]] = bitcast double* [[PTR_ADDR_REF]] to i8* // CHECK: [[BASE_PTR_GEP3_0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[PTR_ADDR_BCAST]], i8** [[BASE_PTR_GEP3_0]], - // CHECK: [[PTR_ADDR_BCAST2:%.+]] = bitcast double* [[PTR_ADDR_REF]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP3_0]] to double** + // CHECK: store double* [[PTR_ADDR_REF]], double** [[BCAST_TOPTR]], // CHECK: [[PTR_GEP3_0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[PTR_ADDR_BCAST2]], i8** [[PTR_GEP3_0]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTR_GEP3_0]] to double** + // CHECK: store double* [[PTR_ADDR_REF]], double** [[BCAST_TOPTR]], // CHECK: [[BASE_PTR_GEP_ARG3:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BASE_PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 // CHECK: [[PTR_GEP_ARG3:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 @@ -407,38 +409,40 @@ struct S1 { // CHECK: store {{.+}}, {{.+}} // firstprivate(b): base_ptr = b, ptr = b, size = 4 (pass by-value) - // CHECK: [[B_CAST_PTR:%.+]] = inttoptr i{{[0-9]+}} [[B_CAST:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP4_1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // CHECK: store i8* [[B_CAST_PTR]], i8** [[BASE_PTRS_GEP4_1]], - // CHECK: [[B_CAST_PTR2:%.+]] = inttoptr i{{[0-9]+}} [[B_CAST:%.+]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_1]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[B_CAST:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP4_1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // CHECK: store i8* [[B_CAST_PTR2]], i8** [[PTRS_GEP4_1]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_1]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[B_CAST]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[SIZES_GEP4_1:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 // CHECK: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_1]], // firstprivate(c), 3 entries: 2, n, c // CHECK: [[BASE_PTRS_GEP4_2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // CHECK: store i8* inttoptr (i{{[0-9]+}} 2 to i8*), i8** [[BASE_PTRS_GEP4_2]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_2]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP4_2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // CHECK: store i8* inttoptr (i{{[0-9]+}} 2 to i8*), i8** [[PTRS_GEP4_2]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_2]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[SIZES_GEP4_2:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK-64: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SIZES_GEP4_2]], // CHECK-32: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_2]], - // CHECK: [[N_PTR:%.+]] = inttoptr i{{[0-9]+}} [[N:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP4_3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 - // CHECK: store i8* [[N_PTR]], i8** [[BASE_PTRS_GEP4_3]], - // CHECK: [[N_PTR2:%.+]] = inttoptr i{{[0-9]+}} [[N:%.+]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_3]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[N:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP4_3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 - // CHECK: store i8* [[N_PTR2]], i8** [[PTRS_GEP4_3]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_3]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[N]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[SIZES_GEP4_3:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 // CHECK-64: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SIZES_GEP4_3]], // CHECK-32: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_3]], - // CHECK: [[B_BCAST:%.+]] = bitcast i{{[0-9]+}}* [[B:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP4_4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 - // CHECK: store i8* [[B_BCAST]], i8** [[BASE_PTRS_GEP4_4]], - // CHECK: [[B_BCAST2:%.+]] = bitcast i{{[0-9]+}}* [[B:%.+]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_4]] to i{{[0-9]+}}** + // CHECK: store i{{[0-9]+}}* [[B:%.+]], i{{[0-9]+}}** [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP4_4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 - // CHECK: store i8* [[B_BCAST2]], i8** [[PTRS_GEP4_4]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_4]] to i{{[0-9]+}}** + // CHECK: store i{{[0-9]+}}* [[B]], i{{[0-9]+}}** [[BCAST_TOPTR]], // CHECK: [[SIZES_GEP4_4:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 // CHECK: store i{{[0-9]+}} [[B_SIZE:%.+]], i{{[0-9]+}}* [[SIZES_GEP4_4]], @@ -492,28 +496,28 @@ struct S1 { // CHECK: [[PTRS5:%.+]] = alloca [3 x i8*], // firstprivate(a): by value - // CHECK: [[A_CAST_PTR:%.+]] = inttoptr i{{[0-9]+}} [[A_CAST:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP5_0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BASE_PTRS5]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[A_CAST_PTR]], i8** [[BASE_PTRS_GEP5_0]], - // CHECK: [[A_CAST_PTR2:%.+]] = inttoptr i{{[0-9]+}} [[A_CAST:%.+]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP5_0]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[A_CAST:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP5_0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[PTRS5]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store i8* [[A_CAST_PTR2]], i8** [[PTRS_GEP5_0]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP5_0]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[A_CAST]], i{{[0-9]+}}* [[BCAST_TOPTR]], // firstprivate(aaa): by value - // CHECK: [[A3_CAST_PTR:%.+]] = inttoptr i{{[0-9]+}} [[A3_CAST:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP5_1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BASE_PTRS5]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // CHECK: store i8* [[A3_CAST_PTR]], i8** [[BASE_PTRS_GEP5_1]], - // CHECK: [[A3_CAST_PTR2:%.+]] = inttoptr i{{[0-9]+}} [[A3_CAST:%.+]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP5_1]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[A3_CAST:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP5_1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[PTRS5]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // CHECK: store i8* [[A3_CAST_PTR2]], i8** [[PTRS_GEP5_1]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP5_1]] to i{{[0-9]+}}* + // CHECK: store i{{[0-9]+}} [[A3_CAST]], i{{[0-9]+}}* [[BCAST_TOPTR]], // firstprivate(b): base_ptr = &b[0], ptr= &b[0] - // CHECK: [[B_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP5_2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BASE_PTRS5]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // CHECK: store i8* [[B_BCAST]], i8** [[BASE_PTRS_GEP5_2]], - // CHECK: [[B_BCAST2:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B:%.+]] to i8* + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP5_2]] to [10 x i{{[0-9]+}}]** + // CHECK: store [10 x i{{[0-9]+}}]* [[B:%.+]], [10 x i{{[0-9]+}}]** [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP5_2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[PTRS5]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // CHECK: store i8* [[B_BCAST2]], i8** [[PTRS_GEP5_2]], + // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP5_2]] to [10 x i{{[0-9]+}}]** + // CHECK: store [10 x i{{[0-9]+}}]* [[B]], [10 x i{{[0-9]+}}]** [[BCAST_TOPTR]], // only check that the right sizes and map types are used // CHECK: call i32 @__tgt_target(i32 -1, {{.+}}, i32 3, i8** {{.+}}, i8** {{.+}}, i[[SZ]]* getelementptr inbounds ([3 x i[[SZ]]], [3 x i[[SZ]]]* [[SIZET5]], i32 0, i32 0), i32* getelementptr inbounds ([3 x i32], [3 x i32]* [[MAPT5]], i32 0, i32 0)) @@ -539,20 +543,20 @@ int bar(int n, double *ptr){ // CHECK: [[PTRS6:%.+]] = alloca [2 x i8*], // firstprivate(a): by value -// CHECK: [[AT_CAST_PTR:%.+]] = inttoptr i{{[0-9]+}} [[AT_CAST:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP6_0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASE_PTRS6]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 -// CHECK: store i8* [[AT_CAST_PTR]], i8** [[BASE_PTRS_GEP6_0]], -// CHECK: [[AT_CAST_PTR2:%.+]] = inttoptr i{{[0-9]+}} [[AT_CAST:%.+]] to i8* +// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP6_0]] to i{{[0-9]+}}* +// CHECK: store i{{[0-9]+}} [[AT_CAST:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP6_0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS6]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 -// CHECK: store i8* [[AT_CAST_PTR2]], i8** [[PTRS_GEP6_0]], +// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP6_0]] to i{{[0-9]+}}* +// CHECK: store i{{[0-9]+}} [[AT_CAST]], i{{[0-9]+}}* [[BCAST_TOPTR]], // firstprivate(b): pointer -// CHECK: [[B_BCAST:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B:%.+]] to i8* // CHECK: [[BASE_PTRS_GEP6_1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASE_PTRS6]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 -// CHECK: store i8* [[B_BCAST]], i8** [[BASE_PTRS_GEP6_1]], -// CHECK: [[B_BCAST2:%.+]] = bitcast [10 x i{{[0-9]+}}]* [[B:%.+]] to i8* +// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP6_1]] to [10 x i{{[0-9]+}}]** +// CHECK: store [10 x i{{[0-9]+}}]* [[B:%.+]], [10 x i{{[0-9]+}}]** [[BCAST_TOPTR]], // CHECK: [[PTRS_GEP6_1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS6]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 -// CHECK: store i8* [[B_BCAST2]], i8** [[PTRS_GEP6_1]], +// CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP6_1]] to [10 x i{{[0-9]+}}]** +// CHECK: store [10 x i{{[0-9]+}}]* [[B]], [10 x i{{[0-9]+}}]** [[BCAST_TOPTR]], // CHECK: call i32 @__tgt_target(i32 -1, {{.+}}, i32 2, i8** {{.+}}, i8** {{.+}}, i[[SZ]]* getelementptr inbounds ([2 x i[[SZ]]], [2 x i[[SZ]]]* [[SIZET6]], i32 0, i32 0), i32* getelementptr inbounds ([2 x i32], [2 x i32]* [[MAPT6]], i32 0, i32 0)) diff --git a/test/OpenMP/target_is_device_ptr_codegen.cpp b/test/OpenMP/target_is_device_ptr_codegen.cpp index 6c807294835a..1a54aa18c00b 100644 --- a/test/OpenMP/target_is_device_ptr_codegen.cpp +++ b/test/OpenMP/target_is_device_ptr_codegen.cpp @@ -46,10 +46,10 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast double* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast double* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK1-DAG: store double* [[VAL:%.+]], double** [[CBP1]] + // CK1-DAG: store double* [[VAL]], double** [[CP1]] // CK1-DAG: [[VAL]] = load double*, double** [[ADDR:@g]], // CK1: call void [[KERNEL:@.+]](double* [[VAL]]) @@ -63,10 +63,10 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast float* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast float* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float** + // CK1-DAG: store float* [[VAL:%.+]], float** [[CBP1]] + // CK1-DAG: store float* [[VAL]], float** [[CP1]] // CK1-DAG: [[VAL]] = load float*, float** [[ADDR:%.+]], // CK1: call void [[KERNEL:@.+]](float* [[VAL]]) @@ -80,10 +80,10 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK1-DAG: store i32* [[VAL:%.+]], i32** [[CBP1]] + // CK1-DAG: store i32* [[VAL]], i32** [[CP1]] // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]], // CK1: call void [[KERNEL:@.+]](i32* [[VAL]]) @@ -97,10 +97,10 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast float* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast float* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float** + // CK1-DAG: store float* [[VAL:%.+]], float** [[CBP1]] + // CK1-DAG: store float* [[VAL]], float** [[CP1]] // CK1-DAG: [[VAL]] = load float*, float** [[ADDR:%.+]], // CK1-DAG: [[ADDR]] = load float**, float*** [[ADDR2:%.+]], @@ -115,10 +115,10 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK1-DAG: store i32* [[VAL:%.+]], i32** [[CBP1]] + // CK1-DAG: store i32* [[VAL]], i32** [[CP1]] // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]], // CK1-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]], @@ -133,10 +133,10 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK1-DAG: store i32* [[VAL:%.+]], i32** [[CBP1]] + // CK1-DAG: store i32* [[VAL]], i32** [[CP1]] // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]], // CK1-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]], @@ -151,19 +151,19 @@ void foo(float *&lr, T *&tr) { // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK1-DAG: store i32* [[VAL:%.+]], i32** [[CBP1]] + // CK1-DAG: store i32* [[VAL]], i32** [[CP1]] // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]], // CK1-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]], // CK1-DAG: [[_BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK1-DAG: [[_P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 - // CK1-DAG: store i8* [[_VALBP:%.+]], i8** [[_BP1]], - // CK1-DAG: store i8* [[_VALP:%.+]], i8** [[_P1]], - // CK1-DAG: [[_VALBP]] = bitcast float* [[_VAL:%.+]] to i8* - // CK1-DAG: [[_VALP]] = bitcast float* [[_VAL]] to i8* + // CK1-DAG: [[_CBP1:%.+]] = bitcast i8** [[_BP1]] to float** + // CK1-DAG: [[_CP1:%.+]] = bitcast i8** [[_P1]] to float** + // CK1-DAG: store float* [[_VAL:%.+]], float** [[_CBP1]] + // CK1-DAG: store float* [[_VAL]], float** [[_CP1]] // CK1-DAG: [[_VAL]] = load float*, float** [[_ADDR:%.+]], // CK1-DAG: [[_ADDR]] = load float**, float*** [[_ADDR2:%.+]], @@ -215,10 +215,10 @@ struct ST { // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%.+]] to i8* + // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** + // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 #pragma omp target is_device_ptr(a) { @@ -231,18 +231,18 @@ struct ST { // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK2-DAG: [[CPVAL0]] = bitcast double*** [[SEC0:%.+]] to i8* + // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double**** + // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK2-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK2-DAG: [[CBPVAL1]] = bitcast double*** [[SEC0]] to i8* - // CK2-DAG: [[CPVAL1]] = bitcast double** [[SEC1:%.+]] to i8* + // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double**** + // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** + // CK2-DAG: store double*** [[SEC0]], double**** [[CBP1]] + // CK2-DAG: store double** [[SEC1:%.+]], double*** [[CP1]] // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]] #pragma omp target is_device_ptr(b) { @@ -255,26 +255,26 @@ struct ST { // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK2-DAG: [[CPVAL0]] = bitcast double*** [[SEC0:%.+]] to i8* + // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double**** + // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK2-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK2-DAG: [[CBPVAL1]] = bitcast double*** [[SEC0]] to i8* - // CK2-DAG: [[CPVAL1]] = bitcast double** [[SEC1:%.+]] to i8* + // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double**** + // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** + // CK2-DAG: store double*** [[SEC0]], double**** [[CBP1]] + // CK2-DAG: store double** [[SEC1:%.+]], double*** [[CP1]] // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]] // CK2-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK2-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK2-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK2-DAG: [[CBPVAL2]] = bitcast [[ST]]* [[VAR2:%.+]] to i8* - // CK2-DAG: [[CPVAL2]] = bitcast double** [[SEC2:%.+]] to i8* + // CK2-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]** + // CK2-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double*** + // CK2-DAG: store [[ST]]* [[VAR2:%.+]], [[ST]]** [[CBP2]] + // CK2-DAG: store double** [[SEC2:%.+]], double*** [[CP2]] // CK2-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 0 #pragma omp target is_device_ptr(a, b) { diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp index 72c7257a0ea7..69e80bb9505b 100644 --- a/test/OpenMP/target_map_codegen.cpp +++ b/test/OpenMP/target_map_codegen.cpp @@ -28,10 +28,10 @@ void implicit_maps_integer (int a){ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK1-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK1-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK1-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK1-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK1-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK1-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK1-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -75,10 +75,10 @@ void implicit_maps_reference (int a, int *b){ // CK2-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK2-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK2-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK2-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK2-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK2-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK2-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK2-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK2-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK2-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -95,10 +95,10 @@ void implicit_maps_reference (int a, int *b){ // CK2-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK2-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK2-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK2-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8* - // CK2-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8* + // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK2-DAG: store i32* [[VAL:%[^,]+]], i32** [[CBP1]] + // CK2-DAG: store i32* [[VAL]], i32** [[CP1]] // CK2-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]], // CK2-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]], @@ -151,10 +151,10 @@ void implicit_maps_parameter (int a){ // CK3-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK3-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK3-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK3-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK3-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK3-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK3-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK3-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK3-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK3-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK3-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK3-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK3-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK3-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -203,10 +203,10 @@ void implicit_maps_nested_integer (int a){ // CK4-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK4-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK4-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK4-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK4-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK4-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK4-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK4-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK4-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK4-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK4-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK4-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK4-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK4-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -257,10 +257,10 @@ void implicit_maps_nested_integer_and_enum (int a){ // CK5-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK5-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK5-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK5-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK5-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK5-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK5-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK5-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK5-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK5-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK5-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK5-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK5-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK5-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -302,10 +302,10 @@ void implicit_maps_host_global (int a){ // CK6-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK6-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK6-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK6-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK6-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK6-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK6-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK6-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK6-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK6-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK6-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK6-64-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK6-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK6-64-DAG: store i32 [[GBLVAL:%.+]], i32* [[CADDR]], @@ -355,18 +355,18 @@ void implicit_maps_double (int a){ // CK7-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK7-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK7-64-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK7-64-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK7-64-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK7-64-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK7-64-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK7-64-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK7-64-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK7-64-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK7-64-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK7-64-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to double* // CK7-64-64-DAG: store double {{.+}}, double* [[CADDR]], - // CK7-32-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK7-32-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK7-32-DAG: [[VALBP]] = bitcast double* [[DECL:%.+]] to i8* - // CK7-32-DAG: [[VALP]] = bitcast double* [[DECL]] to i8* + // CK7-32-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double** + // CK7-32-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK7-32-DAG: store double* [[DECL:%[^,]+]], double** [[CBP1]] + // CK7-32-DAG: store double* [[DECL]], double** [[CP1]] // CK7-64: call void [[KERNEL:@.+]](i[[sz]] [[VAL]]) // CK7-32: call void [[KERNEL:@.+]](double* [[DECL]]) @@ -411,10 +411,10 @@ void implicit_maps_float (int a){ // CK8-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK8-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK8-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK8-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK8-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK8-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK8-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK8-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK8-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK8-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK8-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK8-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK8-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to float* // CK8-DAG: store float {{.+}}, float* [[CADDR]], @@ -455,10 +455,10 @@ void implicit_maps_array (int a){ // CK9-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK9-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK9-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK9-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK9-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK9-DAG: [[VALBP]] = bitcast [2 x double]* [[DECL:%.+]] to i8* - // CK9-DAG: [[VALP]] = bitcast [2 x double]* [[DECL]] to i8* + // CK9-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [2 x double]** + // CK9-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [2 x double]** + // CK9-DAG: store [2 x double]* [[DECL:%[^,]+]], [2 x double]** [[CBP1]] + // CK9-DAG: store [2 x double]* [[DECL]], [2 x double]** [[CP1]] // CK9: call void [[KERNEL:@.+]]([2 x double]* [[DECL]]) #pragma omp target @@ -496,10 +496,10 @@ void implicit_maps_pointer (){ // CK10-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK10-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK10-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK10-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK10-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK10-DAG: [[VALBP]] = bitcast double* [[PTR:%.+]] to i8* - // CK10-DAG: [[VALP]] = bitcast double* [[PTR]] to i8* + // CK10-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double** + // CK10-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK10-DAG: store double* [[PTR:%[^,]+]], double** [[CBP1]] + // CK10-DAG: store double* [[PTR]], double** [[CP1]] // CK10: call void [[KERNEL:@.+]](double* [[PTR]]) #pragma omp target @@ -538,10 +538,10 @@ void implicit_maps_double_complex (int a){ // CK11-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK11-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK11-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK11-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK11-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK11-DAG: [[VALBP]] = bitcast { double, double }* [[PTR:%.+]] to i8* - // CK11-DAG: [[VALP]] = bitcast { double, double }* [[PTR]] to i8* + // CK11-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to { double, double }** + // CK11-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to { double, double }** + // CK11-DAG: store { double, double }* [[PTR:%[^,]+]], { double, double }** [[CBP1]] + // CK11-DAG: store { double, double }* [[PTR]], { double, double }** [[CP1]] // CK11: call void [[KERNEL:@.+]]({ double, double }* [[PTR]]) #pragma omp target @@ -584,18 +584,18 @@ void implicit_maps_float_complex (int a){ // CK12-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK12-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK12-64-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK12-64-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK12-64-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK12-64-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK12-64-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK12-64-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK12-64-DAG: store i[[sz]] [[VAL:%[^,]+]], i[[sz]]* [[CBP1]] + // CK12-64-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK12-64-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK12-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to { float, float }* // CK12-64-DAG: store { float, float } {{.+}}, { float, float }* [[CADDR]], - // CK12-32-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK12-32-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK12-32-DAG: [[VALBP]] = bitcast { float, float }* [[DECL:%.+]] to i8* - // CK12-32-DAG: [[VALP]] = bitcast { float, float }* [[DECL]] to i8* + // CK12-32-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to { float, float }** + // CK12-32-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to { float, float }** + // CK12-32-DAG: store { float, float }* [[DECL:%[^,]+]], { float, float }** [[CBP1]] + // CK12-32-DAG: store { float, float }* [[DECL]], { float, float }** [[CP1]] // CK12-64: call void [[KERNEL:@.+]](i[[sz]] [[VAL]]) // CK12-32: call void [[KERNEL:@.+]]({ float, float }* [[DECL]]) @@ -645,27 +645,29 @@ void implicit_maps_variable_length_array (int a){ // CK13-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK13-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 // CK13-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[SS]], i32 0, i32 0 - // CK13-DAG: store i8* inttoptr (i[[sz]] 2 to i8*), i8** [[BP0]], - // CK13-DAG: store i8* inttoptr (i[[sz]] 2 to i8*), i8** [[P0]], + // CK13-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[sz]]* + // CK13-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[sz]]* + // CK13-DAG: store i[[sz]] 2, i[[sz]]* [[CBP0]] + // CK13-DAG: store i[[sz]] 2, i[[sz]]* [[CP0]] // CK13-DAG: store i[[sz]] {{8|4}}, i[[sz]]* [[S0]], // CK13-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK13-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 // CK13-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[SS]], i32 0, i32 1 - // CK13-DAG: store i8* [[VALBP1:%.+]], i8** [[BP1]], - // CK13-DAG: store i8* [[VALP1:%.+]], i8** [[P1]], - // CK13-DAG: [[VALBP1]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK13-DAG: [[VALP1]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK13-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK13-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK13-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] + // CK13-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK13-DAG: store i[[sz]] {{8|4}}, i[[sz]]* [[S1]], // CK13-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2 // CK13-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2 // CK13-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[SS]], i32 0, i32 2 - // CK13-DAG: store i8* [[VALBP2:%.+]], i8** [[BP2]], - // CK13-DAG: store i8* [[VALP2:%.+]], i8** [[P2]], + // CK13-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double** + // CK13-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** + // CK13-DAG: store double* [[DECL:%.+]], double** [[CBP2]] + // CK13-DAG: store double* [[DECL]], double** [[CP2]] // CK13-DAG: store i[[sz]] [[VALS2:%.+]], i[[sz]]* [[S2]], - // CK13-DAG: [[VALBP2]] = bitcast double* [[DECL:%.+]] to i8* - // CK13-DAG: [[VALP2]] = bitcast double* [[DECL]] to i8* // CK13-DAG: [[VALS2]] = mul nuw i[[sz]] %{{.+}}, 8 // CK13: call void [[KERNEL:@.+]](i[[sz]] {{.+}}, i[[sz]] {{.+}}, double* [[DECL]]) @@ -730,17 +732,17 @@ void implicit_maps_class (int a){ // CK14-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK14-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK14-DAG: store i8* [[VALBP0:%.+]], i8** [[BP0]], - // CK14-DAG: store i8* [[VALP0:%.+]], i8** [[P0]], - // CK14-DAG: [[VALBP0]] = bitcast [[ST]]* [[DECL:%.+]] to i8* - // CK14-DAG: [[VALP0]] = bitcast [[ST]]* [[DECL]] to i8* + // CK14-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK14-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK14-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]] + // CK14-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CP0]] // CK14-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK14-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 - // CK14-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK14-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK14-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK14-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK14-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK14-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] + // CK14-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK14-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK14-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK14-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -822,17 +824,17 @@ void implicit_maps_templated_class (int a){ // CK15-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK15-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK15-DAG: store i8* [[VALBP0:%.+]], i8** [[BP0]], - // CK15-DAG: store i8* [[VALP0:%.+]], i8** [[P0]], - // CK15-DAG: [[VALBP0]] = bitcast [[ST]]* [[DECL:%.+]] to i8* - // CK15-DAG: [[VALP0]] = bitcast [[ST]]* [[DECL]] to i8* + // CK15-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK15-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK15-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]] + // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CP0]] // CK15-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK15-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 - // CK15-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK15-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK15-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK15-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK15-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] + // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK15-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK15-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK15-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -847,17 +849,17 @@ void implicit_maps_templated_class (int a){ // CK15-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK15-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK15-DAG: store i8* [[VALBP0:%.+]], i8** [[BP0]], - // CK15-DAG: store i8* [[VALP0:%.+]], i8** [[P0]], - // CK15-DAG: [[VALBP0]] = bitcast [[ST]]* [[DECL:%.+]] to i8* - // CK15-DAG: [[VALP0]] = bitcast [[ST]]* [[DECL]] to i8* + // CK15-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK15-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK15-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]] + // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CP0]] // CK15-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK15-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 - // CK15-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK15-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK15-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK15-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK15-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] + // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK15-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK15-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK15-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -923,10 +925,10 @@ void implicit_maps_templated_function (int a){ // CK16-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK16-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK16-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK16-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK16-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK16-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK16-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK16-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK16-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] + // CK16-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK16-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK16-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK16-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -971,10 +973,10 @@ void implicit_maps_struct (int a){ // CK17-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK17-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK17-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK17-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK17-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK17-DAG: [[VALBP]] = bitcast [[ST]]* [[DECL:%.+]] to i8* - // CK17-DAG: [[VALP]] = bitcast [[ST]]* [[DECL]] to i8* + // CK17-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** + // CK17-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[ST]]** + // CK17-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP1]] + // CK17-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CP1]] // CK17: call void [[KERNEL:@.+]]([[ST]]* [[DECL]]) #pragma omp target @@ -1023,10 +1025,10 @@ void implicit_maps_template_type_capture (int a){ // CK18-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK18-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK18-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK18-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK18-DAG: [[VALBP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* - // CK18-DAG: [[VALP]] = inttoptr i[[sz]] [[VAL:%.+]] to i8* + // CK18-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* + // CK18-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* + // CK18-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] + // CK18-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] // CK18-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK18-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK18-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -1054,6 +1056,9 @@ void implicit_maps_template_type_capture (int a){ // CK19: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] // CK19: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i32] [i32 32] +// CK19: [[SIZE00n:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] +// CK19: [[MTYPE00n:@.+]] = private {{.*}}constant [1 x i32] [i32 32] + // CK19: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400] // CK19: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i32] [i32 33] @@ -1181,10 +1186,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK19: call void [[CALL00:@.+]](i32* {{[^,]+}}) #pragma omp target map(alloc:a) @@ -1192,6 +1197,28 @@ void explicit_maps_single (int ii){ ++a; } + // Map of a scalar in nested region. + int b = a; + + // Region 00n + // CK19-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00n]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00n]]{{.+}}) + // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] + // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + + // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[VAR0]], i32** [[CP0]] + + // CK19: call void [[CALL00n:@.+]](i32* {{[^,]+}}) + #pragma omp target map(alloc:b) + #pragma omp parallel + { + ++b; + } + // Map of an array. int arra[100]; @@ -1202,10 +1229,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [100 x i32]* [[VAR0]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x i32]** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store [100 x i32]* [[VAR0]], [100 x i32]** [[CP0]] // CK19: call void [[CALL01:@.+]]([100 x i32]* {{[^,]+}}) #pragma omp target map(to:arra) @@ -1220,10 +1247,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 20 // CK19: call void [[CALL02:@.+]]([100 x i32]* {{[^,]+}}) @@ -1239,10 +1266,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 // CK19: call void [[CALL03:@.+]]([100 x i32]* {{[^,]+}}) @@ -1258,10 +1285,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 // CK19: call void [[CALL04:@.+]]([100 x i32]* {{[^,]+}}) @@ -1277,10 +1304,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 15 // CK19: call void [[CALL05:@.+]]([100 x i32]* {{[^,]+}}) @@ -1298,11 +1325,11 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* // CK19-DAG: [[CSVAL0]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} %{{.*}} @@ -1321,11 +1348,11 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* // CK19-DAG: [[CSVAL0]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 @@ -1342,10 +1369,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [100 x i32]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} %{{.*}} // CK19: call void [[CALL08:@.+]]([100 x i32]* {{[^,]+}}) @@ -1364,10 +1391,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32** [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32** [[VAR0]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32*** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32*** + // CK19-DAG: store i32** [[VAR0:%.+]], i32*** [[CBP0]] + // CK19-DAG: store i32** [[VAR0]], i32*** [[CP0]] // CK19: call void [[CALL09:@.+]](i32** {{[^,]+}}) #pragma omp target map(from:pa) @@ -1382,10 +1409,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 20 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -1403,10 +1430,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -1424,10 +1451,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 15 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -1447,11 +1474,11 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* // CK19-DAG: [[CSVAL0]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} %{{.*}} @@ -1472,11 +1499,11 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* // CK19-DAG: [[CSVAL0]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 @@ -1495,10 +1522,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} %{{.*}} // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -1521,20 +1548,20 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[VAR1]], i32** [[CP1]] // CK19-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[VAR1]] to i8* // CK19-DAG: [[CSVAL1]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19: call void [[CALL16:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) @@ -1550,17 +1577,17 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 20 // CK19: call void [[CALL17:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) @@ -1576,17 +1603,17 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 0 // CK19: call void [[CALL18:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) @@ -1604,20 +1631,20 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK19-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* // CK19-DAG: [[CSVAL1]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 0 @@ -1634,17 +1661,17 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 15 // CK19: call void [[CALL20:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) @@ -1662,20 +1689,20 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK19-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* // CK19-DAG: [[CSVAL1]] = mul nuw i{{.+}} %{{.*}}, 4 // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} %{{.+}} @@ -1692,17 +1719,17 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = inttoptr i[[Z]] %{{.+}} to i8* - // CK19-DAG: [[CPVAL0]] = inttoptr i[[Z]] %{{.+}}to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} %{{.+}} // CK19: call void [[CALL22:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) @@ -1719,10 +1746,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK19: call void [[CALL23:@.+]](i32* {{[^,]+}}) #pragma omp target map(always, tofrom: a) @@ -1741,10 +1768,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [4 x [5 x [6 x i32]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [4 x [5 x [6 x i32]]]* [[VAR0]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [4 x [5 x [6 x i32]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [4 x [5 x [6 x i32]]]** + // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0:%.+]], [4 x [5 x [6 x i32]]]** [[CBP0]] + // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0]], [4 x [5 x [6 x i32]]]** [[CP0]] // CK19: call void [[CALL24:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) #pragma omp target map(tofrom: marr) @@ -1759,10 +1786,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [4 x [5 x [6 x i32]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [4 x [5 x [6 x i32]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0:%.+]], [4 x [5 x [6 x i32]]]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[6 x i32]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC00]] = getelementptr {{.*}}[5 x [6 x i32]]* [[SEC000:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC000]] = getelementptr {{.*}}[4 x [5 x [6 x i32]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 @@ -1780,10 +1807,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [4 x [5 x [6 x i32]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [4 x [5 x [6 x i32]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0:%.+]], [4 x [5 x [6 x i32]]]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[6 x i32]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[SEC00]] = getelementptr {{.*}}[5 x [6 x i32]]* [[SEC000:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC000]] = getelementptr {{.*}}[4 x [5 x [6 x i32]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 @@ -1801,10 +1828,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [4 x [5 x [6 x i32]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [4 x [5 x [6 x i32]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0:%.+]], [4 x [5 x [6 x i32]]]** [[CBP0]] + // CK19-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[6 x i32]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK19-DAG: [[SEC00]] = getelementptr {{.*}}[5 x [6 x i32]]* [[SEC000:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC000]] = getelementptr {{.*}}[4 x [5 x [6 x i32]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 @@ -1822,20 +1849,20 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32*** [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32*** [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32**** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**** + // CK19-DAG: store i32*** [[VAR0:%.+]], i32**** [[CBP0]] + // CK19-DAG: store i32*** [[SEC0:%.+]], i32**** [[CP0]] // CK19-DAG: [[VAR0]] = load i32***, i32**** [[PTR:%[^,]+]], // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32*** [[SEC00:[^,]+]], i{{.+}} 1 // CK19-DAG: [[SEC00]] = load i32***, i32**** [[PTR]], // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32*** [[SEC0]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32** [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32**** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32*** + // CK19-DAG: store i32*** [[SEC0]], i32**** [[CBP1]] + // CK19-DAG: store i32** [[SEC1:%.+]], i32*** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32** [[SEC11:[^,]+]], i{{.+}} 2 // CK19-DAG: [[SEC11]] = load i32**, i32*** [[SEC111:%[^,]+]], // CK19-DAG: [[SEC111]] = getelementptr {{.*}}i32*** [[SEC1111:[^,]+]], i{{.+}} 1 @@ -1843,10 +1870,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK19-DAG: [[CBPVAL2]] = bitcast i32** [[SEC1]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast i32* [[SEC2:%.+]] to i8* + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i32*** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32** + // CK19-DAG: store i32** [[SEC1]], i32*** [[CBP2]] + // CK19-DAG: store i32* [[SEC2:%.+]], i32** [[CP2]] // CK19-DAG: [[SEC2]] = getelementptr {{.*}}i32* [[SEC22:[^,]+]], i{{.+}} 2 // CK19-DAG: [[SEC22]] = load i32*, i32** [[SEC222:%[^,]+]], // CK19-DAG: [[SEC222]] = getelementptr {{.*}}i32** [[SEC2222:[^,]+]], i{{.+}} 2 @@ -1867,20 +1894,20 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast i32*** [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast i32*** [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32**** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32**** + // CK19-DAG: store i32*** [[VAR0:%.+]], i32**** [[CBP0]] + // CK19-DAG: store i32*** [[SEC0:%.+]], i32**** [[CP0]] // CK19-DAG: [[VAR0]] = load i32***, i32**** [[PTR:%[^,]+]], // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32*** [[SEC00:[^,]+]], i{{.+}} 1 // CK19-DAG: [[SEC00]] = load i32***, i32**** [[PTR]], // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast i32*** [[SEC0]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast i32** [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32**** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32*** + // CK19-DAG: store i32*** [[SEC0]], i32**** [[CBP1]] + // CK19-DAG: store i32** [[SEC1:%.+]], i32*** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32** [[SEC11:[^,]+]], i{{.+}} 2 // CK19-DAG: [[SEC11]] = load i32**, i32*** [[SEC111:%[^,]+]], // CK19-DAG: [[SEC111]] = getelementptr {{.*}}i32*** [[SEC1111:[^,]+]], i{{.+}} 1 @@ -1888,10 +1915,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK19-DAG: [[CBPVAL2]] = bitcast i32** [[SEC1]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast i32* [[SEC2:%.+]] to i8* + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i32*** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32** + // CK19-DAG: store i32** [[SEC1]], i32*** [[CBP2]] + // CK19-DAG: store i32* [[SEC2:%.+]], i32** [[CP2]] // CK19-DAG: [[SEC2]] = getelementptr {{.*}}i32* [[SEC22:[^,]+]], i{{.+}} 3 // CK19-DAG: [[SEC22]] = load i32*, i32** [[SEC222:%[^,]+]], // CK19-DAG: [[SEC222]] = getelementptr {{.*}}i32** [[SEC2222:[^,]+]], i{{.+}} 2 @@ -1917,40 +1944,42 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 23 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 23 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CP0]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* // CK19-64-DAG: [[VAR1]] = zext i32 %{{[^,]+}} to i64 // CK19-64-DAG: [[VAR11]] = zext i32 %{{[^,]+}} to i64 // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i[[Z]]* + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR2:%.+]], i[[Z]]* [[CBP2]] + // CK19-DAG: store i[[Z]] [[VAR22:%.+]], i[[Z]]* [[CP2]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S2]] - // CK19-DAG: [[CBPVAL2]] = inttoptr i[[Z]] [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = inttoptr i[[Z]] [[VAR22:%.+]] to i8* // CK19-64-DAG: [[VAR2]] = zext i32 %{{[^,]+}} to i64 // CK19-64-DAG: [[VAR22]] = zext i32 %{{[^,]+}} to i64 // // CK19-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK19-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 // CK19-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] - // CK19-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] + // CK19-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double** + // CK19-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** + // CK19-DAG: store double* [[VAR3:%.+]], double** [[CBP3]] + // CK19-DAG: store double* [[VAR3]], double** [[CP3]] // CK19-DAG: store i[[Z]] [[CSVAL3:%[^,]+]], i[[Z]]* [[S3]] - // CK19-DAG: [[CBPVAL3]] = bitcast double* [[VAR3:%.+]] to i8* - // CK19-DAG: [[CPVAL3]] = bitcast double* [[VAR3]] to i8* // CK19-DAG: [[CSVAL3]] = mul nuw i[[Z]] %{{[^,]+}}, {{8|4}} // CK19: call void [[CALL30:@.+]](i[[Z]] 23, i[[Z]] %{{[^,]+}}, i[[Z]] %{{[^,]+}}, double* %{{[^,]+}}) @@ -1966,29 +1995,31 @@ void explicit_maps_single (int ii){ // // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 23 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 23 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CP0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK19-DAG: [[CBPVAL2]] = inttoptr i[[Z]] [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = inttoptr i[[Z]] [[VAR22:%.+]] to i8* + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i[[Z]]* + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR2:%.+]], i[[Z]]* [[CBP2]] + // CK19-DAG: store i[[Z]] [[VAR22:%.+]], i[[Z]]* [[CP2]] // // CK19-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK19-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] - // CK19-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] - // CK19-DAG: [[CBPVAL3]] = bitcast double* [[VAR3:%.+]] to i8* - // CK19-DAG: [[CPVAL3]] = bitcast double* [[SEC3:%.+]] to i8* + // CK19-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double** + // CK19-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** + // CK19-DAG: store double* [[VAR3:%.+]], double** [[CBP3]] + // CK19-DAG: store double* [[SEC3:%.+]], double** [[CP3]] // CK19-DAG: [[SEC3]] = getelementptr {{.*}}double* [[SEC33:%.+]], i[[Z]] 0 // CK19-DAG: [[SEC33]] = getelementptr {{.*}}double* [[SEC333:%.+]], i[[Z]] [[IDX3:%.+]] // CK19-DAG: [[IDX3]] = mul nsw i[[Z]] %{{[^,]+}}, %{{[^,]+}} @@ -2013,10 +2044,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0]], [11 x [12 x [13 x double]]]** [[CP0]] // CK19: call void [[CALL32:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) #pragma omp target map(marras) @@ -2031,10 +2062,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [12 x [13 x double]]* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [12 x [13 x double]]** + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] + // CK19-DAG: store [12 x [13 x double]]* [[SEC0:%.+]], [12 x [13 x double]]** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 0 // CK19: call void [[CALL33:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) @@ -2050,10 +2081,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [12 x [13 x double]]* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [12 x [13 x double]]** + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] + // CK19-DAG: store [12 x [13 x double]]* [[SEC0:%.+]], [12 x [13 x double]]** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 0 // CK19: call void [[CALL34:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) @@ -2072,11 +2103,11 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] + // CK19-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] // CK19-DAG: store i[[Z]] [[CSVAL0:%[^,]+]], i[[Z]]* [[S0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [13 x double]* [[SEC0:%.+]] to i8* // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[12 x [13 x double]]* [[SEC00:%[^,]+]], i[[Z]] 0, i[[Z]] 0 // CK19-DAG: [[SEC00]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 1 // CK19-DAG: [[CSVAL0]] = mul nuw i[[Z]] %{{[^,]+}}, 104 @@ -2094,10 +2125,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [13 x double]* [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] + // CK19-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[13 x double]* [[SEC00:%[^,]+]], i{{.+}} 0 // CK19-DAG: [[SEC00]] = getelementptr {{.+}}[12 x [13 x double]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[SEC000]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 @@ -2117,27 +2148,29 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-DAG: store [13 x double]* [[VAR2]], [13 x double]** [[CP2]] // CK19-DAG: store i[[Z]] [[CSVAL2:%[^,]+]], i[[Z]]* [[S2]] - // CK19-DAG: [[CBPVAL2]] = bitcast [13 x double]* [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast [13 x double]* [[VAR2]] to i8* // CK19-DAG: [[CSVAL2]] = mul nuw i[[Z]] %{{[^,]+}}, 104 // CK19: call void [[CALL37:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) @@ -2155,27 +2188,29 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] // CK19-DAG: store i[[Z]] [[CSVAL2:%[^,]+]], i[[Z]]* [[S2]] - // CK19-DAG: [[CBPVAL2]] = bitcast [13 x double]* [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast [13 x double]* [[SEC2:%.+]] to i8* // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC22:%[^,]+]] // CK19-DAG: [[SEC22]] = mul nsw i[[Z]] 0, %{{[^,]+}} // CK19-DAG: [[CSVAL2]] = mul nuw i[[Z]] %{{[^,]+}}, 104 @@ -2195,27 +2230,29 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] // CK19-DAG: store i[[Z]] [[CSVAL2:%[^,]+]], i[[Z]]* [[S2]] - // CK19-DAG: [[CBPVAL2]] = bitcast [13 x double]* [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast [13 x double]* [[SEC2:%.+]] to i8* // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC22:%[^,]+]] // CK19-DAG: [[SEC22]] = mul nsw i[[Z]] 0, %{{[^,]+}} // CK19-DAG: [[CSVAL2]] = mul nuw i[[Z]] %{{[^,]+}}, 104 @@ -2235,27 +2272,29 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // CK19-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] // CK19-DAG: store i[[Z]] [[CSVAL2:%[^,]+]], i[[Z]]* [[S2]] - // CK19-DAG: [[CBPVAL2]] = bitcast [13 x double]* [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast [13 x double]* [[SEC2:%.+]] to i8* // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[SEC22:%[^,]+]], i[[Z]] 0 // CK19-DAG: [[SEC22]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC222:%[^,]+]] // CK19-DAG: [[SEC222]] = mul nsw i[[Z]] 1, %{{[^,]+}} @@ -2273,22 +2312,24 @@ void explicit_maps_single (int ii){ // // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[BP0]] - // CK19-DAG: store i8* inttoptr (i[[Z]] 11 to i8*), i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] // // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = inttoptr i[[Z]] [[VAR1:%.+]] to i8* - // CK19-DAG: [[CPVAL1]] = inttoptr i[[Z]] [[VAR11:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK19-DAG: [[CBPVAL2]] = bitcast [13 x double]* [[VAR2:%.+]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast [13 x double]* [[SEC2:%.+]] to i8* + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[SEC22:%[^,]+]], i[[Z]] 0 // CK19-DAG: [[SEC22]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC222:%[^,]+]] // CK19-DAG: [[SEC222]] = mul nsw i[[Z]] 0, %{{[^,]+}} @@ -2306,20 +2347,20 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK19-DAG: [[CBPVAL0]] = bitcast double*** [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast double*** [[SEC0:%.+]] to i8* + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to double**** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double**** + // CK19-DAG: store double*** [[VAR0:%.+]], double**** [[CBP0]] + // CK19-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]] // CK19-DAG: [[VAR0]] = load double***, double**** [[PTR:%[^,]+]], // CK19-DAG: [[SEC0]] = getelementptr {{.*}}double*** [[SEC00:[^,]+]], i{{.+}} 0 // CK19-DAG: [[SEC00]] = load double***, double**** [[PTR]], // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK19-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK19-DAG: [[CBPVAL1]] = bitcast double*** [[SEC0]] to i8* - // CK19-DAG: [[CPVAL1]] = bitcast double** [[SEC1:%.+]] to i8* + // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double**** + // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** + // CK19-DAG: store double*** [[SEC0]], double**** [[CBP1]] + // CK19-DAG: store double** [[SEC1:%.+]], double*** [[CP1]] // CK19-DAG: [[SEC1]] = getelementptr {{.*}}double** [[SEC11:[^,]+]], i{{.+}} 2 // CK19-DAG: [[SEC11]] = load double**, double*** [[SEC111:%[^,]+]], // CK19-DAG: [[SEC111]] = getelementptr {{.*}}double*** [[SEC1111:[^,]+]], i{{.+}} 0 @@ -2327,10 +2368,10 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK19-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK19-DAG: [[CBPVAL2]] = bitcast double** [[SEC1]] to i8* - // CK19-DAG: [[CPVAL2]] = bitcast double* [[SEC2:%.+]] to i8* + // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double*** + // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** + // CK19-DAG: store double** [[SEC1]], double*** [[CBP2]] + // CK19-DAG: store double* [[SEC2:%.+]], double** [[CP2]] // CK19-DAG: [[SEC2]] = getelementptr {{.*}}double* [[SEC22:[^,]+]], i{{.+}} 0 // CK19-DAG: [[SEC22]] = load double*, double** [[SEC222:%[^,]+]], // CK19-DAG: [[SEC222]] = getelementptr {{.*}}double** [[SEC2222:[^,]+]], i{{.+}} 2 @@ -2354,11 +2395,11 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK19-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [11 x [12 x [13 x double]]]** + // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] + // CK19-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] // CK19-DAG: store i[[Z]] [[CSVAL0:%[^,]+]], i[[Z]]* [[S0]] - // CK19-DAG: [[CBPVAL0]] = bitcast [11 x [12 x [13 x double]]]* [[VAR0:%.+]] to i8* - // CK19-DAG: [[CPVAL0]] = bitcast [13 x double]* [[SEC0:%.+]] to i8* // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[12 x [13 x double]]* [[SEC00:%[^,]+]], i[[Z]] 0, i[[Z]] 0 // CK19-DAG: [[SEC00]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 1 // CK19-DAG: [[CSVAL0]] = mul nuw i[[Z]] %{{[^,]+}}, 104 @@ -2372,6 +2413,7 @@ void explicit_maps_single (int ii){ } // CK19: define {{.+}}[[CALL00]] +// CK19: define {{.+}}[[CALL00n]] // CK19: define {{.+}}[[CALL01]] // CK19: define {{.+}}[[CALL02]] // CK19: define {{.+}}[[CALL03]] @@ -2453,10 +2495,10 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // CK20-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK20-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK20-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK20-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK20-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK20-DAG: [[CPVAL0]] = bitcast i32* [[RVAR00:%.+]] to i8* + // CK20-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK20-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK20-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK20-DAG: store i32* [[RVAR00:%.+]], i32** [[CP0]] // CK20-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK20-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -2473,10 +2515,10 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // CK20-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK20-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK20-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK20-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK20-DAG: [[CBPVAL0]] = bitcast [10 x i32]* [[RVAR0:%.+]] to i8* - // CK20-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK20-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [10 x i32]** + // CK20-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK20-DAG: store [10 x i32]* [[RVAR0:%.+]], [10 x i32]** [[CBP0]] + // CK20-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK20-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[RVAR00:%.+]], i{{.+}} 0, i{{.+}} 0 // CK20-DAG: [[RVAR0]] = load [10 x i32]*, [10 x i32]** [[VAR0:%[^,]+]] // CK20-DAG: [[RVAR00]] = load [10 x i32]*, [10 x i32]** [[VAR0]] @@ -2494,10 +2536,10 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // CK20-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK20-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK20-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK20-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK20-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8* - // CK20-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8* + // CK20-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK20-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK20-DAG: store float* [[VAR0:%.+]], float** [[CBP0]] + // CK20-DAG: store float* [[VAR0]], float** [[CP0]] // CK20: call void [[CALL02:@.+]](float* {{[^,]+}}) #pragma omp target map(from:b) @@ -2512,10 +2554,10 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // CK20-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK20-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK20-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK20-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK20-DAG: [[CBPVAL0]] = bitcast float* [[RVAR0:%.+]] to i8* - // CK20-DAG: [[CPVAL0]] = bitcast float* [[SEC0:%.+]] to i8* + // CK20-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK20-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK20-DAG: store float* [[RVAR0:%.+]], float** [[CBP0]] + // CK20-DAG: store float* [[SEC0:%.+]], float** [[CP0]] // CK20-DAG: [[RVAR0]] = load float*, float** [[VAR0:%[^,]+]] // CK20-DAG: [[SEC0]] = getelementptr {{.*}}float* [[RVAR00:%.+]], i{{.+}} 2 // CK20-DAG: [[RVAR00]] = load float*, float** [[VAR0]] @@ -2580,10 +2622,10 @@ struct CC { // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK21-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK21-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK21-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK21-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0:%.+]], i{{.+}} 0, i{{.+}} 0 // CK21: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}}) @@ -2599,10 +2641,10 @@ struct CC { // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK21-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK21-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK21-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK21-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK21-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK21-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK21-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -2620,18 +2662,18 @@ struct CC { // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK21-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK21-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK21-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK21-DAG: [[CPVAL0]] = bitcast float** [[SEC0:%.+]] to i8* + // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float*** + // CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK21-DAG: store float** [[SEC0:%.+]], float*** [[CP0]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK21-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK21-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK21-DAG: [[CBPVAL1]] = bitcast float** [[SEC0]] to i8* - // CK21-DAG: [[CPVAL1]] = bitcast float* [[SEC1:%.+]] to i8* + // CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float*** + // CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float** + // CK21-DAG: store float** [[SEC0]], float*** [[CBP1]] + // CK21-DAG: store float* [[SEC1:%.+]], float** [[CP1]] // CK21-DAG: [[SEC1]] = getelementptr {{.*}}float* [[RVAR1:%[^,]+]], i{{.+}} 123 // CK21-DAG: [[RVAR1]] = load float*, float** [[SEC1_:%[^,]+]] // CK21-DAG: [[SEC1_]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 @@ -2649,10 +2691,10 @@ struct CC { // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK21-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK21-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK21-DAG: [[CBPVAL0]] = bitcast [123 x float]* [[VAR0:%.+]] to i8* - // CK21-DAG: [[CPVAL0]] = bitcast [123 x float]* [[VAR0]] to i8* + // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [123 x float]** + // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [123 x float]** + // CK21-DAG: store [123 x float]* [[VAR0:%.+]], [123 x float]** [[CBP0]] + // CK21-DAG: store [123 x float]* [[VAR0]], [123 x float]** [[CP0]] // CK21: call void [[CALL03:@.+]]([123 x float]* {{[^,]+}}) #pragma omp target map(from:la) @@ -2667,10 +2709,10 @@ struct CC { // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK21-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK21-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK21-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK21-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK21-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK21-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK21: call void [[CALL04:@.+]](i32* {{[^,]+}}) #pragma omp target map(from:arg) @@ -2686,18 +2728,18 @@ struct CC { // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK21-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK21-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK21-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK21-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK21-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK21-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK21-DAG: [[CBPVAL1]] = bitcast [[ST]]* [[VAR1:%.+]] to i8* - // CK21-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** + // CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK21-DAG: store [[ST]]* [[VAR1:%.+]], [[ST]]** [[CBP1]] + // CK21-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK21-DAG: [[SEC1]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 // CK21: call void [[CALL05:@.+]]([[ST]]* {{[^,]+}}) @@ -2809,8 +2851,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast (i32* @a to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast (i32* @a to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK22-DAG: store i32* @a, i32** [[CBP0]] + // CK22-DAG: store i32* @a, i32** [[CP0]] // CK22: call void [[CALL00:@.+]](i32* {{[^,]+}}) #pragma omp target map(a) @@ -2823,8 +2867,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([100 x i32]* @c to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([100 x i32]* @c to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x i32]** + // CK22-DAG: store [100 x i32]* @c, [100 x i32]** [[CBP0]] + // CK22-DAG: store [100 x i32]* @c, [100 x i32]** [[CP0]] // CK22: call void [[CALL01:@.+]]([100 x i32]* {{[^,]+}}) #pragma omp target map(c) @@ -2837,8 +2883,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast (i32** @d to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast (i32** @d to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32*** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32*** + // CK22-DAG: store i32** @d, i32*** [[CBP0]] + // CK22-DAG: store i32** @d, i32*** [[CP0]] // CK22: call void [[CALL02:@.+]](i32** {{[^,]+}}) #pragma omp target map(d) @@ -2851,8 +2899,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([100 x i32]* @c to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast (i32* getelementptr inbounds ([100 x i32], [100 x i32]* @c, i{{.+}} 0, i{{.+}} 1) to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x i32]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK22-DAG: store [100 x i32]* @c, [100 x i32]** [[CBP0]] + // CK22-DAG: store i32* getelementptr inbounds ([100 x i32], [100 x i32]* @c, i{{.+}} 0, i{{.+}} 1), i32** [[CP0]] // CK22: call void [[CALL03:@.+]]([100 x i32]* {{[^,]+}}) #pragma omp target map(c[1:4]) @@ -2865,10 +2915,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK22-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK22-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK22-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK22-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK22-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK22-DAG: [[RVAR0]] = load i32*, i32** @d // CK22-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 2 // CK22-DAG: [[RVAR00]] = load i32*, i32** @d @@ -2884,8 +2934,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([[ST]]* @sa to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([[ST]]* @sa to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK22-DAG: store [[ST]]* @sa, [[ST]]** [[CBP0]] + // CK22-DAG: store [[ST]]* @sa, [[ST]]** [[CP0]] // CK22: call void [[CALL05:@.+]]([[ST]]* {{[^,]+}}) #pragma omp target map(sa) @@ -2898,8 +2950,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([100 x [[ST]]]* @sc to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([100 x [[ST]]]* @sc to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x [[ST]]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x [[ST]]]** + // CK22-DAG: store [100 x [[ST]]]* @sc, [100 x [[ST]]]** [[CBP0]] + // CK22-DAG: store [100 x [[ST]]]* @sc, [100 x [[ST]]]** [[CP0]] // CK22: call void [[CALL06:@.+]]([100 x [[ST]]]* {{[^,]+}}) #pragma omp target map(sc) @@ -2912,8 +2966,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([[ST]]** @sd to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([[ST]]** @sd to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]*** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]*** + // CK22-DAG: store [[ST]]** @sd, [[ST]]*** [[CBP0]] + // CK22-DAG: store [[ST]]** @sd, [[ST]]*** [[CP0]] // CK22: call void [[CALL07:@.+]]([[ST]]** {{[^,]+}}) #pragma omp target map(sd) @@ -2926,8 +2982,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([100 x [[ST]]]* @sc to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([[ST]]* getelementptr inbounds ([100 x [[ST]]], [100 x [[ST]]]* @sc, i{{.+}} 0, i{{.+}} 1) to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x [[ST]]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK22-DAG: store [100 x [[ST]]]* @sc, [100 x [[ST]]]** [[CBP0]] + // CK22-DAG: store [[ST]]* getelementptr inbounds ([100 x [[ST]]], [100 x [[ST]]]* @sc, i{{.+}} 0, i{{.+}} 1), [[ST]]** [[CP0]] // CK22: call void [[CALL08:@.+]]([100 x [[ST]]]* {{[^,]+}}) #pragma omp target map(sc[1:4]) @@ -2940,10 +2998,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK22-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK22-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[RVAR0:%.+]] to i8* - // CK22-DAG: [[CPVAL0]] = bitcast [[ST]]* [[SEC0:%.+]] to i8* + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK22-DAG: store [[ST]]* [[RVAR0:%.+]], [[ST]]** [[CBP0]] + // CK22-DAG: store [[ST]]* [[SEC0:%.+]], [[ST]]** [[CP0]] // CK22-DAG: [[RVAR0]] = load [[ST]]*, [[ST]]** @sd // CK22-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[RVAR00:%.+]], i{{.+}} 2 // CK22-DAG: [[RVAR00]] = load [[ST]]*, [[ST]]** @sd @@ -2959,8 +3017,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([[STT]]* @sta to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([[STT]]* @sta to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[STT]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[STT]]** + // CK22-DAG: store [[STT]]* @sta, [[STT]]** [[CBP0]] + // CK22-DAG: store [[STT]]* @sta, [[STT]]** [[CP0]] // CK22: call void [[CALL10:@.+]]([[STT]]* {{[^,]+}}) #pragma omp target map(sta) @@ -2973,8 +3033,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([100 x [[STT]]]* @stc to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([100 x [[STT]]]* @stc to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x [[STT]]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x [[STT]]]** + // CK22-DAG: store [100 x [[STT]]]* @stc, [100 x [[STT]]]** [[CBP0]] + // CK22-DAG: store [100 x [[STT]]]* @stc, [100 x [[STT]]]** [[CP0]] // CK22: call void [[CALL11:@.+]]([100 x [[STT]]]* {{[^,]+}}) #pragma omp target map(stc) @@ -2987,8 +3049,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([[STT]]** @std to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([[STT]]** @std to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[STT]]*** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[STT]]*** + // CK22-DAG: store [[STT]]** @std, [[STT]]*** [[CBP0]] + // CK22-DAG: store [[STT]]** @std, [[STT]]*** [[CP0]] // CK22: call void [[CALL12:@.+]]([[STT]]** {{[^,]+}}) #pragma omp target map(std) @@ -3001,8 +3065,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* bitcast ([100 x [[STT]]]* @stc to i8*), i8** [[BP0]] - // CK22-DAG: store i8* bitcast ([[STT]]* getelementptr inbounds ([100 x [[STT]]], [100 x [[STT]]]* @stc, i{{.+}} 0, i{{.+}} 1) to i8*), i8** [[P0]] + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x [[STT]]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[STT]]** + // CK22-DAG: store [100 x [[STT]]]* @stc, [100 x [[STT]]]** [[CBP0]] + // CK22-DAG: store [[STT]]* getelementptr inbounds ([100 x [[STT]]], [100 x [[STT]]]* @stc, i{{.+}} 0, i{{.+}} 1), [[STT]]** [[CP0]] // CK22: call void [[CALL13:@.+]]([100 x [[STT]]]* {{[^,]+}}) #pragma omp target map(stc[1:4]) @@ -3015,10 +3081,10 @@ int explicit_maps_globals(void){ // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK22-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK22-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK22-DAG: [[CBPVAL0]] = bitcast [[STT]]* [[RVAR0:%.+]] to i8* - // CK22-DAG: [[CPVAL0]] = bitcast [[STT]]* [[SEC0:%.+]] to i8* + // CK22-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[STT]]** + // CK22-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[STT]]** + // CK22-DAG: store [[STT]]* [[RVAR0:%.+]], [[STT]]** [[CBP0]] + // CK22-DAG: store [[STT]]* [[SEC0:%.+]], [[STT]]** [[CP0]] // CK22-DAG: [[RVAR0]] = load [[STT]]*, [[STT]]** @std // CK22-DAG: [[SEC0]] = getelementptr {{.*}}[[STT]]* [[RVAR00:%.+]], i{{.+}} 2 // CK22-DAG: [[RVAR00]] = load [[STT]]*, [[STT]]** @std @@ -3088,10 +3154,10 @@ int explicit_maps_inside_captured(int a){ // CK23-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK23-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK23-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK23-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK23-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK23-DAG: [[CPVAL0]] = bitcast i32* [[VAR00:%.+]] to i8* + // CK23-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK23-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK23-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK23-DAG: store i32* [[VAR00:%.+]], i32** [[CP0]] // CK23-DAG: [[VAR0]] = load i32*, i32** [[CAP0:%[^,]+]] // CK23-DAG: [[CAP0]] = getelementptr inbounds [[SA]], [[SA]] // CK23-DAG: [[VAR00]] = load i32*, i32** [[CAP00:%[^,]+]] @@ -3107,10 +3173,10 @@ int explicit_maps_inside_captured(int a){ // CK23-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK23-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK23-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK23-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK23-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8* - // CK23-DAG: [[CPVAL0]] = bitcast float* [[VAR00:%.+]] to i8* + // CK23-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK23-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK23-DAG: store float* [[VAR0:%.+]], float** [[CBP0]] + // CK23-DAG: store float* [[VAR00:%.+]], float** [[CP0]] // CK23-DAG: [[VAR0]] = load float*, float** [[CAP0:%[^,]+]] // CK23-DAG: [[CAP0]] = getelementptr inbounds [[SA]], [[SA]] // CK23-DAG: [[VAR00]] = load float*, float** [[CAP00:%[^,]+]] @@ -3126,10 +3192,10 @@ int explicit_maps_inside_captured(int a){ // CK23-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK23-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK23-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK23-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK23-DAG: [[CBPVAL0]] = bitcast [100 x float]* [[VAR0:%.+]] to i8* - // CK23-DAG: [[CPVAL0]] = bitcast [100 x float]* [[VAR00:%.+]] to i8* + // CK23-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x float]** + // CK23-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [100 x float]** + // CK23-DAG: store [100 x float]* [[VAR0:%.+]], [100 x float]** [[CBP0]] + // CK23-DAG: store [100 x float]* [[VAR00:%.+]], [100 x float]** [[CP0]] // CK23-DAG: [[VAR0]] = load [100 x float]*, [100 x float]** [[CAP0:%[^,]+]] // CK23-DAG: [[CAP0]] = getelementptr inbounds [[SA]], [[SA]] // CK23-DAG: [[VAR00]] = load [100 x float]*, [100 x float]** [[CAP00:%[^,]+]] @@ -3146,10 +3212,10 @@ int explicit_maps_inside_captured(int a){ // CK23-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK23-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK23-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK23-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK23-DAG: [[CBPVAL0]] = bitcast float** [[VAR0:%.+]] to i8* - // CK23-DAG: [[CPVAL0]] = bitcast float** [[VAR00:%.+]] to i8* + // CK23-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float*** + // CK23-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float*** + // CK23-DAG: store float** [[VAR0:%.+]], float*** [[CBP0]] + // CK23-DAG: store float** [[VAR00:%.+]], float*** [[CP0]] // CK23-DAG: [[VAR0]] = load float**, float*** [[CAP0:%[^,]+]] // CK23-DAG: [[CAP0]] = getelementptr inbounds [[SA]], [[SA]] // CK23-DAG: [[VAR00]] = load float**, float*** [[CAP00:%[^,]+]] @@ -3165,10 +3231,10 @@ int explicit_maps_inside_captured(int a){ // CK23-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK23-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK23-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK23-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK23-DAG: [[CBPVAL0]] = bitcast [100 x float]* [[VAR0:%.+]] to i8* - // CK23-DAG: [[CPVAL0]] = bitcast float* [[SEC0:%.+]] to i8* + // CK23-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [100 x float]** + // CK23-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK23-DAG: store [100 x float]* [[VAR0:%.+]], [100 x float]** [[CBP0]] + // CK23-DAG: store float* [[SEC0:%.+]], float** [[CP0]] // CK23-DAG: [[SEC0]] = getelementptr {{.*}}[100 x float]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK23-DAG: [[VAR0]] = load [100 x float]*, [100 x float]** [[CAP0:%[^,]+]] // CK23-DAG: [[CAP0]] = getelementptr inbounds [[SA]], [[SA]] @@ -3186,10 +3252,10 @@ int explicit_maps_inside_captured(int a){ // CK23-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK23-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK23-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK23-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK23-DAG: [[CBPVAL0]] = bitcast float* [[RVAR0:%.+]] to i8* - // CK23-DAG: [[CPVAL0]] = bitcast float* [[SEC0:%.+]] to i8* + // CK23-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK23-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK23-DAG: store float* [[RVAR0:%.+]], float** [[CBP0]] + // CK23-DAG: store float* [[SEC0:%.+]], float** [[CP0]] // CK23-DAG: [[RVAR0]] = load float*, float** [[VAR0:%[^,]+]] // CK23-DAG: [[SEC0]] = getelementptr {{.*}}float* [[RVAR00:%.+]], i{{.+}} 2 // CK23-DAG: [[RVAR00]] = load float*, float** [[VAR00:%[^,]+]] @@ -3328,10 +3394,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 // CK24: call void [[CALL01:@.+]]([[SC]]* {{[^,]+}}) @@ -3345,10 +3411,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]* [[SEC0:%.+]], [[SA]]** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 @@ -3363,10 +3429,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 @@ -3382,10 +3448,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 3 @@ -3400,18 +3466,18 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SB]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SB]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast [[SB]]* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SB]]** +// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] +// CK24-DAG: store [[SB]]* [[SEC1:%.+]], [[SB]]** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 @@ -3427,10 +3493,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[10 x [[SA]]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 2 @@ -3447,20 +3513,20 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SA]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3 @@ -3478,18 +3544,18 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SB]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SB]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 @@ -3505,19 +3571,19 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SA]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SB]]* [[SEC1111:[^,]+]], i{{.+}} 0, i{{.+}} 4 @@ -3534,10 +3600,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SA]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 1 @@ -3554,19 +3620,19 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SA]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[10 x i32]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC11]] = getelementptr {{.*}}[[SA]]* [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC111]] = load [[SA]]*, [[SA]]** [[SEC1111:%[^,]+]], @@ -3584,28 +3650,28 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SB]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SB]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast [[SA]]** [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]*** +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CBP1]] +// CK24-DAG: store [[SA]]** [[SEC1:%.+]], [[SA]]*** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 -// CK24-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] -// CK24-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] -// CK24-DAG: [[CBPVAL2]] = bitcast [[SA]]** [[SEC1]] to i8* -// CK24-DAG: [[CPVAL2]] = bitcast [[SA]]** [[SEC2:%.+]] to i8* +// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]*** +// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [[SA]]*** +// CK24-DAG: store [[SA]]** [[SEC1:%.+]], [[SA]]*** [[CBP2]] +// CK24-DAG: store [[SA]]** [[SEC2:%.+]], [[SA]]*** [[CP2]] // CK24-DAG: [[SEC2]] = getelementptr {{.*}}[[SA]]* [[SEC22:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC22]] = load [[SA]]*, [[SA]]** [[SEC222:%[^,]+]], // CK24-DAG: [[SEC222]] = getelementptr {{.*}}[[SB]]* [[SEC2222:%[^,]+]], i{{.+}} 0, i{{.+}} 4 @@ -3614,10 +3680,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 -// CK24-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] -// CK24-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] -// CK24-DAG: [[CBPVAL3]] = bitcast [[SA]]** [[SEC2]] to i8* -// CK24-DAG: [[CPVAL3]] = bitcast i32* [[SEC3:%.+]] to i8* +// CK24-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to [[SA]]*** +// CK24-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32** +// CK24-DAG: store [[SA]]** [[SEC2]], [[SA]]*** [[CBP3]] +// CK24-DAG: store i32* [[SEC3:%.+]], i32** [[CP3]] // CK24-DAG: [[SEC3]] = getelementptr {{.*}}[[SA]]* [[SEC33:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC33]] = load [[SA]]*, [[SA]]** [[SEC333:%[^,]+]], // CK24-DAG: [[SEC333]] = getelementptr {{.*}}[[SA]]* [[SEC3333:%[^,]+]], i{{.+}} 0, i{{.+}} 1 @@ -3640,10 +3706,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} @@ -3660,10 +3726,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]* [[SEC0:%.+]], [[SA]]** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 @@ -3681,10 +3747,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 @@ -3703,10 +3769,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 3 @@ -3724,18 +3790,18 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SB]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SB]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast [[SB]]* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SB]]** +// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] +// CK24-DAG: store [[SB]]* [[SEC1:%.+]], [[SB]]** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2 @@ -3755,10 +3821,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[10 x [[SA]]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 2 @@ -3778,20 +3844,20 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SA]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3 @@ -3813,18 +3879,18 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SB]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SB]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2 @@ -3844,19 +3910,19 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SA]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SB]]* [[SEC1111:[^,]+]], i{{.+}} 0, i{{.+}} 4 @@ -3877,10 +3943,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SA]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 1 @@ -3900,19 +3966,19 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SA]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SA]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[10 x i32]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC11]] = getelementptr {{.*}}[[SA]]* [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC111]] = load [[SA]]*, [[SA]]** [[SEC1111:%[^,]+]], @@ -3934,28 +4000,28 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK24-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK24-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK24-DAG: [[CBPVAL0]] = bitcast [[SC]]* [[VAR0:%.+]] to i8* -// CK24-DAG: [[CPVAL0]] = bitcast [[SB]]** [[SEC0:%.+]] to i8* +// CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** +// CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** +// CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] +// CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK24-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK24-DAG: [[CBPVAL1]] = bitcast [[SB]]** [[SEC0]] to i8* -// CK24-DAG: [[CPVAL1]] = bitcast [[SA]]** [[SEC1:%.+]] to i8* +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]*** +// CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] +// CK24-DAG: store [[SA]]** [[SEC1:%.+]], [[SA]]*** [[CP1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 -// CK24-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] -// CK24-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] -// CK24-DAG: [[CBPVAL2]] = bitcast [[SA]]** [[SEC1]] to i8* -// CK24-DAG: [[CPVAL2]] = bitcast [[SA]]** [[SEC2:%.+]] to i8* +// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]*** +// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [[SA]]*** +// CK24-DAG: store [[SA]]** [[SEC1]], [[SA]]*** [[CBP2]] +// CK24-DAG: store [[SA]]** [[SEC2:%.+]], [[SA]]*** [[CP2]] // CK24-DAG: [[SEC2]] = getelementptr {{.*}}[[SA]]* [[SEC22:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC22]] = load [[SA]]*, [[SA]]** [[SEC222:%[^,]+]], // CK24-DAG: [[SEC222]] = getelementptr {{.*}}[[SB]]* [[SEC2222:%[^,]+]], i{{.+}} 0, i{{.+}} 4 @@ -3964,10 +4030,10 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 -// CK24-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] -// CK24-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] -// CK24-DAG: [[CBPVAL3]] = bitcast [[SA]]** [[SEC2]] to i8* -// CK24-DAG: [[CPVAL3]] = bitcast i32* [[SEC3:%.+]] to i8* +// CK24-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to [[SA]]*** +// CK24-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32** +// CK24-DAG: store [[SA]]** [[SEC2]], [[SA]]*** [[CBP3]] +// CK24-DAG: store i32* [[SEC3:%.+]], i32** [[CP3]] // CK24-DAG: [[SEC3]] = getelementptr {{.*}}[[SA]]* [[SEC33:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC33]] = load [[SA]]*, [[SA]]** [[SEC333:%[^,]+]], // CK24-DAG: [[SEC333]] = getelementptr {{.*}}[[SA]]* [[SEC3333:%[^,]+]], i{{.+}} 0, i{{.+}} 1 @@ -4047,10 +4113,10 @@ struct CC { // CK25-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK25-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK25-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK25-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK25-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK25-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK25-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK25-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK25-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK25-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK25-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0:%.+]], i{{.+}} 0, i{{.+}} 0 // CK25: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}}) @@ -4068,10 +4134,10 @@ struct CC { // CK25-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK25-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK25-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK25-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK25-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK25-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK25-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK25-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK25-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK25-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK25: call void [[CALL01:@.+]](i32* {{[^,]+}}) #pragma omp target map(to:arg) @@ -4151,17 +4217,17 @@ struct CC { // CK26-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK26-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK26-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK26-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK26-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK26-DAG: [[CPVAL0]] = bitcast [[ST]]* [[VAR0]] to i8* + // CK26-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK26-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK26-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK26-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] // CK26-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK26-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK26-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK26-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK26-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK26-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK26-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK26-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK26-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK26-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK26-DAG: [[VAR1]] = load i32*, i32** [[PVT:%.+]], // CK26-DAG: [[SEC1]] = load i32*, i32** [[PVT]], @@ -4178,17 +4244,17 @@ struct CC { // CK26-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK26-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK26-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK26-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK26-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK26-DAG: [[CPVAL0]] = bitcast [[ST]]* [[VAR0]] to i8* + // CK26-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK26-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK26-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK26-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] // CK26-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK26-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK26-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK26-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK26-DAG: [[CBPVAL1]] = bitcast float* [[VAR1:%.+]] to i8* - // CK26-DAG: [[CPVAL1]] = bitcast float* [[SEC1:%.+]] to i8* + // CK26-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float** + // CK26-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float** + // CK26-DAG: store float* [[VAR1:%.+]], float** [[CBP1]] + // CK26-DAG: store float* [[SEC1:%.+]], float** [[CP1]] // CK26-DAG: [[VAR1]] = load float*, float** [[PVT:%.+]], // CK26-DAG: [[SEC1]] = load float*, float** [[PVT]], @@ -4205,17 +4271,17 @@ struct CC { // CK26-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK26-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK26-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK26-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK26-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK26-DAG: [[CPVAL0]] = bitcast [[ST]]* [[VAR0]] to i8* + // CK26-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK26-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK26-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK26-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] // CK26-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK26-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK26-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK26-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK26-DAG: [[CBPVAL1]] = bitcast i32* [[VAR1:%.+]] to i8* - // CK26-DAG: [[CPVAL1]] = bitcast i32* [[SEC1:%.+]] to i8* + // CK26-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK26-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK26-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK26-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] // CK26-DAG: [[VAR1]] = load i32*, i32** [[PVT:%.+]], // CK26-DAG: [[SEC1]] = load i32*, i32** [[PVT]], @@ -4232,17 +4298,17 @@ struct CC { // CK26-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK26-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK26-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK26-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK26-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* - // CK26-DAG: [[CPVAL0]] = bitcast [[ST]]* [[VAR0]] to i8* + // CK26-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK26-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** + // CK26-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] + // CK26-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] // CK26-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK26-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK26-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK26-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK26-DAG: [[CBPVAL1]] = bitcast float* [[VAR1:%.+]] to i8* - // CK26-DAG: [[CPVAL1]] = bitcast float* [[SEC1:%.+]] to i8* + // CK26-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float** + // CK26-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float** + // CK26-DAG: store float* [[VAR1:%.+]], float** [[CBP1]] + // CK26-DAG: store float* [[SEC1:%.+]], float** [[CP1]] // CK26-DAG: [[VAR1]] = load float*, float** [[PVT:%.+]], // CK26-DAG: [[SEC1]] = load float*, float** [[PVT]], @@ -4335,10 +4401,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK27-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK27-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK27-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK27-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK27-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK27-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK27-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK27-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK27-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK27: call void [[CALL00:@.+]](i32* {{[^,]+}}) #pragma omp target @@ -4353,10 +4419,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK27-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK27-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK27-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK27-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK27-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK27-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK27-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK27-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK27-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK27-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK27-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK27-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -4374,10 +4440,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK27-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK27-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK27-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK27-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK27-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK27-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK27-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK27-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK27-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK27-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK27-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK27-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -4395,10 +4461,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK27-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK27-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK27-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK27-DAG: [[CBPVAL0]] = bitcast i32* [[RVAR0:%.+]] to i8* - // CK27-DAG: [[CPVAL0]] = bitcast i32* [[SEC0:%.+]] to i8* + // CK27-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK27-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK27-DAG: store i32* [[RVAR0:%.+]], i32** [[CBP0]] + // CK27-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] // CK27-DAG: [[RVAR0]] = load i32*, i32** [[VAR0:%[^,]+]] // CK27-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} %{{.+}} // CK27-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] @@ -4428,10 +4494,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK27-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK27-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK27-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK27-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK27-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK27-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK27-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK27-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK27-DAG: store i32* [[VAR0]], i32** [[CP0]] // CK27: call void [[CALL05:@.+]](i32* {{[^,]+}}) #pragma omp target firstprivate(pvtPtr) @@ -4453,10 +4519,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 // CK27-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK27-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 - // CK27-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]], - // CK27-DAG: store i8* [[VALP:%.+]], i8** [[P1]], - // CK27-DAG: [[VALBP]] = inttoptr i[[Z]] [[VAL:%.+]] to i8* - // CK27-DAG: [[VALP]] = inttoptr i[[Z]] [[VAL:%.+]] to i8* + // CK27-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK27-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK27-DAG: store i[[Z]] [[VAL:%.+]], i[[Z]]* [[CBP1]] + // CK27-DAG: store i[[Z]] [[VAL]], i[[Z]]* [[CP1]] // CK27-DAG: [[VAL]] = load i[[Z]], i[[Z]]* [[ADDR:%.+]], // CK27-64-DAG: [[CADDR:%.+]] = bitcast i[[Z]]* [[ADDR]] to i32* // CK27-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -4482,10 +4548,10 @@ void zero_size_section_and_private_maps (int ii){ // CK27-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK27-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK27-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK27-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK27-DAG: [[CBPVAL0]] = bitcast [10 x i32]* [[VAR0:%.+]] to i8* - // CK27-DAG: [[CPVAL0]] = bitcast [10 x i32]* [[VAR0]] to i8* + // CK27-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [10 x i32]** + // CK27-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [10 x i32]** + // CK27-DAG: store [10 x i32]* [[VAR0:%.+]], [10 x i32]** [[CBP0]] + // CK27-DAG: store [10 x i32]* [[VAR0]], [10 x i32]** [[CP0]] // CK27: call void [[CALL09:@.+]]([10 x i32]* {{[^,]+}}) #pragma omp target firstprivate(pvtArr) @@ -4529,10 +4595,10 @@ void explicit_maps_pointer_references (int *p){ // CK28-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK28-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK28-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK28-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK28-DAG: [[CBPVAL0]] = bitcast i32** [[VAR0:%.+]] to i8* - // CK28-DAG: [[CPVAL0]] = bitcast i32** [[VAR1:%.+]] to i8* + // CK28-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32*** + // CK28-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32*** + // CK28-DAG: store i32** [[VAR0:%.+]], i32*** [[CBP0]] + // CK28-DAG: store i32** [[VAR1:%.+]], i32*** [[CP0]] // CK28-DAG: [[VAR0]] = load i32**, i32*** [[VAR00:%.+]], // CK28-DAG: [[VAR1]] = load i32**, i32*** [[VAR11:%.+]], @@ -4549,10 +4615,10 @@ void explicit_maps_pointer_references (int *p){ // CK28-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK28-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK28-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK28-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK28-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK28-DAG: [[CPVAL0]] = bitcast i32* [[VAR1:%.+]] to i8* + // CK28-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK28-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK28-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK28-DAG: store i32* [[VAR1:%.+]], i32** [[CP0]] // CK28-DAG: [[VAR0]] = load i32*, i32** [[VAR00:%.+]], // CK28-DAG: [[VAR00]] = load i32**, i32*** [[VAR000:%.+]], // CK28-DAG: [[VAR1]] = getelementptr inbounds i32, i32* [[VAR11:%.+]], i{{64|32}} 2 @@ -4609,36 +4675,36 @@ struct SSB{ // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK29-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK29-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK29-DAG: [[CBPVAL0]] = bitcast [[SSB]]* [[VAR0:%.+]] to i8* - // CK29-DAG: [[CPVAL0]] = bitcast [[SSA]]** [[VAR00:%.+]] to i8* + // CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]** + // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]** + // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]] + // CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]] // CK29-DAG: [[VAR0]] = load [[SSB]]*, [[SSB]]** % // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 0 // CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK29-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK29-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK29-DAG: [[CBPVAL1]] = bitcast [[SSA]]** [[VAR00]] to i8* - // CK29-DAG: [[CPVAL1]] = bitcast double*** [[VAR1:%.+]] to i8* + // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]*** + // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**** + // CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]] + // CK29-DAG: store double*** [[VAR1:%.+]], double**** [[CP1]] // CK29-DAG: [[VAR1]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK29-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK29-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK29-DAG: [[CBPVAL2]] = bitcast double*** [[VAR1]] to i8* - // CK29-DAG: [[CPVAL2]] = bitcast double** [[VAR2:%.+]] to i8* + // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double**** + // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double*** + // CK29-DAG: store double*** [[VAR1]], double**** [[CBP2]] + // CK29-DAG: store double** [[VAR2:%.+]], double*** [[CP2]] // CK29-DAG: [[VAR2]] = load double**, double*** [[VAR22:%.+]], // CK29-DAG: [[VAR22]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] - // CK29-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] - // CK29-DAG: [[CBPVAL3]] = bitcast double** [[VAR2]] to i8* - // CK29-DAG: [[CPVAL3]] = bitcast double* [[VAR3:%.+]] to i8* + // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double*** + // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** + // CK29-DAG: store double** [[VAR2]], double*** [[CBP3]] + // CK29-DAG: store double* [[VAR3:%.+]], double** [[CP3]] // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0 // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}}, @@ -4656,34 +4722,34 @@ struct SSB{ // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK29-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK29-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK29-DAG: [[CBPVAL0]] = bitcast [[SSB]]* [[VAR0:%.+]] to i8* - // CK29-DAG: [[CPVAL0]] = bitcast [[SSA]]*** [[VAR00:%.+]] to i8* + // CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]** + // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**** + // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]] + // CK29-DAG: store [[SSA]]*** [[VAR00:%.+]], [[SSA]]**** [[CP0]] // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1 // CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK29-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK29-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK29-DAG: [[CBPVAL1]] = bitcast [[SSA]]*** [[VAR00]] to i8* - // CK29-DAG: [[CPVAL1]] = bitcast [[SSA]]** [[VAR1:%.+]] to i8* + // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]**** + // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SSA]]*** + // CK29-DAG: store [[SSA]]*** [[VAR00]], [[SSA]]**** [[CBP1]] + // CK29-DAG: store [[SSA]]** [[VAR1:%.+]], [[SSA]]*** [[CP1]] // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]], // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK29-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK29-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK29-DAG: [[CBPVAL2]] = bitcast [[SSA]]** [[VAR1]] to i8* - // CK29-DAG: [[CPVAL2]] = bitcast double** [[VAR2:%.+]] to i8* + // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SSA]]*** + // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double*** + // CK29-DAG: store [[SSA]]** [[VAR1]], [[SSA]]*** [[CBP2]] + // CK29-DAG: store double** [[VAR2:%.+]], double*** [[CP2]] // CK29-DAG: [[VAR2]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 0 // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] - // CK29-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] - // CK29-DAG: [[CBPVAL3]] = bitcast double** [[VAR2]] to i8* - // CK29-DAG: [[CPVAL3]] = bitcast double* [[VAR3:%.+]] to i8* + // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double*** + // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** + // CK29-DAG: store double** [[VAR2]], double*** [[CBP3]] + // CK29-DAG: store double* [[VAR3:%.+]], double** [[CP3]] // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0 // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}}, @@ -4701,42 +4767,42 @@ struct SSB{ // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK29-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK29-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK29-DAG: [[CBPVAL0]] = bitcast [[SSB]]* [[VAR0:%.+]] to i8* - // CK29-DAG: [[CPVAL0]] = bitcast [[SSA]]*** [[VAR00:%.+]] to i8* + // CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]** + // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**** + // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]] + // CK29-DAG: store [[SSA]]*** [[VAR00:%.+]], [[SSA]]**** [[CP0]] // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1 // CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK29-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] - // CK29-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK29-DAG: [[CBPVAL1]] = bitcast [[SSA]]*** [[VAR00]] to i8* - // CK29-DAG: [[CPVAL1]] = bitcast [[SSA]]** [[VAR1:%.+]] to i8* + // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]**** + // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SSA]]*** + // CK29-DAG: store [[SSA]]*** [[VAR00]], [[SSA]]**** [[CBP1]] + // CK29-DAG: store [[SSA]]** [[VAR1:%.+]], [[SSA]]*** [[CP1]] // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]], // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK29-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]] - // CK29-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]] - // CK29-DAG: [[CBPVAL2]] = bitcast [[SSA]]** [[VAR1]] to i8* - // CK29-DAG: [[CPVAL2]] = bitcast double*** [[VAR2:%.+]] to i8* + // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SSA]]*** + // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**** + // CK29-DAG: store [[SSA]]** [[VAR1]], [[SSA]]*** [[CBP2]] + // CK29-DAG: store double*** [[VAR2:%.+]], double**** [[CP2]] // CK29-DAG: [[VAR2]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]] - // CK29-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]] - // CK29-DAG: [[CBPVAL3]] = bitcast double*** [[VAR2]] to i8* - // CK29-DAG: [[CPVAL3]] = bitcast double** [[VAR3:%.+]] to i8* + // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double**** + // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double*** + // CK29-DAG: store double*** [[VAR2]], double**** [[CBP3]] + // CK29-DAG: store double** [[VAR3:%.+]], double*** [[CP3]] // CK29-DAG: [[VAR3]] = load double**, double*** [[VAR2]], // CK29-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 4 // CK29-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 4 - // CK29-DAG: store i8* [[CBPVAL4:%[^,]+]], i8** [[BP4]] - // CK29-DAG: store i8* [[CPVAL4:%[^,]+]], i8** [[P4]] - // CK29-DAG: [[CBPVAL4]] = bitcast double** [[VAR3]] to i8* - // CK29-DAG: [[CPVAL4]] = bitcast double* [[VAR4:%.+]] to i8* + // CK29-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to double*** + // CK29-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to double** + // CK29-DAG: store double** [[VAR3]], double*** [[CBP4]] + // CK29-DAG: store double* [[VAR4:%.+]], double** [[CP4]] // CK29-DAG: [[VAR4]] = getelementptr inbounds double, double* [[VAR44:%.+]], i{{.+}} 0 // CK29-DAG: [[VAR44]] = load double*, double** diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp index 0801f631ee17..3063ab16abc8 100644 --- a/test/OpenMP/target_parallel_codegen.cpp +++ b/test/OpenMP/target_parallel_codegen.cpp @@ -121,10 +121,10 @@ int foo(int n) { // CHECK-DAG: [[P]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR:%[^,]+]], i32 0, i32 0 // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BPR]], i32 0, i32 [[IDX0:[0-9]+]] // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR]], i32 0, i32 [[IDX0]] - // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] - // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] - // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[VAL0:%.+]], i[[SZ]]* [[CBPADDR0]], + // CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]], // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4 @@ -148,17 +148,17 @@ int foo(int n) { // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0 - // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] - // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] - // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[VAL0:%.+]], i[[SZ]]* [[CBPADDR0]], + // CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]], // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1 - // CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] - // CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] - // CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P1]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] [[VAL1:%.+]], i[[SZ]]* [[CBPADDR1]], + // CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]], // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] @@ -232,56 +232,58 @@ int foo(int n) { // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. - // CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* - // CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* - // CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR0:%.+]], + // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR0:%.+]], + // CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8* - // CHECK-DAG: [[P1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8* - // CHECK-DAG: store i8* [[BP1]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P1]], i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CBPADDR1:%.+]], + // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CPADDR1:%.+]], + // CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}} - // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CBPADDR2:%.+]], + // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CPADDR2:%.+]], + // CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8* - // CHECK-DAG: [[P3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8* - // CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CBPADDR3:%.+]], + // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CPADDR3:%.+]], + // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8* - // CHECK-DAG: [[P4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}} + // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CBPADDR4:%.+]], + // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CPADDR4:%.+]], + // CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [10 x float]** + // CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [10 x float]** // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP5:%[^,]+]] = bitcast float* %{{.+}} to i8* - // CHECK-DAG: [[P5:%[^,]+]] = bitcast float* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP5]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P5]], i8** {{%[^,]+}} + // CHECK-DAG: store float* %{{.+}}, float** [[CBPADDR5:%.+]], + // CHECK-DAG: store float* %{{.+}}, float** [[CPADDR5:%.+]], + // CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to float** + // CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to float** // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8* - // CHECK-DAG: [[P6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP6]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P6]], i8** {{%[^,]+}} + // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CBPADDR6:%.+]], + // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CPADDR6:%.+]], + // CHECK-DAG: [[CBPADDR6]] = bitcast i8** {{%[^,]+}} to [5 x [10 x double]]** + // CHECK-DAG: [[CPADDR6]] = bitcast i8** {{%[^,]+}} to [5 x [10 x double]]** // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP7:%[^,]+]] = bitcast double* %{{.+}} to i8* - // CHECK-DAG: [[P7:%[^,]+]] = bitcast double* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP7]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P7]], i8** {{%[^,]+}} + // CHECK-DAG: store double* %{{.+}}, double** [[CBPADDR7:%.+]], + // CHECK-DAG: store double* %{{.+}}, double** [[CPADDR7:%.+]], + // CHECK-DAG: [[CBPADDR7]] = bitcast i8** {{%[^,]+}} to double** + // CHECK-DAG: [[CPADDR7]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8* - // CHECK-DAG: [[P8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP8]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P8]], i8** {{%[^,]+}} + // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CBPADDR8:%.+]], + // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CPADDR8:%.+]], + // CHECK-DAG: [[CBPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]** + // CHECK-DAG: [[CPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]** // CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* {{%[^,]+}} // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 @@ -550,32 +552,34 @@ int bar(int n){ // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. -// CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* -// CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* -// CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}} +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR0:%.+]], +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR0:%.+]], +// CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}} -// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}} +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR1:%.+]], +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR1:%.+]], +// CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: [[BP2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8* -// CHECK-DAG: [[P2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8* -// CHECK-DAG: store i8* [[BP2]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P2]], i8** {{%[^,]+}} +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR2:%.+]], +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR2:%.+]], +// CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: [[BP3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8* -// CHECK-DAG: [[P3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8* -// CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}} +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: [[BP4:%[^,]+]] = bitcast i16* %{{.+}} to i8* -// CHECK-DAG: [[P4:%[^,]+]] = bitcast i16* %{{.+}} to i8* -// CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}} +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 @@ -600,29 +604,31 @@ int bar(int n){ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 0 -// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] -// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] -// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8* -// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8* +// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL0:%.+]], i[[SZ]]* [[CBPADDR0]], +// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]], // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 1 -// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] -// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] -// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8* -// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8* +// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL1:%.+]], i[[SZ]]* [[CBPADDR1]], +// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]], // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 2 // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 2 -// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]] -// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]] +// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL2:%.+]], i[[SZ]]* [[CBPADDR2]], +// CHECK-DAG: store i[[SZ]] [[VAL2]], i[[SZ]]* [[CPADDR2]], // CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 3 // CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 3 -// CHECK-DAG: store i8* [[BP3:%[^,]+]], i8** [[BPADDR3]] -// CHECK-DAG: store i8* [[P3:%[^,]+]], i8** [[PADDR3]] -// CHECK-DAG: [[BP3]] = bitcast [10 x i32]* %{{.+}} to i8* -// CHECK-DAG: [[P3]] = bitcast [10 x i32]* %{{.+}} to i8* +// CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to [10 x i32]** +// CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to [10 x i32]** +// CHECK-DAG: store [10 x i32]* [[VAL3:%.+]], [10 x i32]** [[CBPADDR3]], +// CHECK-DAG: store [10 x i32]* [[VAL3]], [10 x i32]** [[CPADDR3]], // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] @@ -652,24 +658,24 @@ int bar(int n){ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 0 -// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] -// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] -// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8* -// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8* +// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL0:%.+]], i[[SZ]]* [[CBPADDR0]], +// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0]], // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 1 -// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] -// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] -// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8* -// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8* +// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VAL1:%.+]], i[[SZ]]* [[CBPADDR1]], +// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1]], // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 2 // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 2 -// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]] -// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]] -// CHECK-DAG: [[BP2]] = bitcast [10 x i32]* %{{.+}} to i8* -// CHECK-DAG: [[P2]] = bitcast [10 x i32]* %{{.+}} to i8* +// CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to [10 x i32]** +// CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to [10 x i32]** +// CHECK-DAG: store [10 x i32]* [[VAL2:%.+]], [10 x i32]** [[CBPADDR2]], +// CHECK-DAG: store [10 x i32]* [[VAL2]], [10 x i32]** [[CPADDR2]], // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp index 4b08a6015afe..208cda6bb350 100644 --- a/test/OpenMP/target_teams_codegen.cpp +++ b/test/OpenMP/target_teams_codegen.cpp @@ -121,10 +121,10 @@ int foo(int n) { // CHECK-DAG: [[P]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR:%[^,]+]], i32 0, i32 0 // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BPR]], i32 0, i32 [[IDX0:[0-9]+]] // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[PR]], i32 0, i32 [[IDX0]] - // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] - // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] - // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CBPADDR0]] + // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CPADDR0]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK: [[RET2:%.+]] = load i32, i32* [[RHV]], align 4 @@ -148,17 +148,17 @@ int foo(int n) { // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 0 - // CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] - // CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] - // CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P0]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CBPADDR0]] + // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CPADDR0]] // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P]], i32 0, i32 1 - // CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] - // CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] - // CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] %{{.+}} to i8* - // CHECK-DAG: [[P1]] = inttoptr i[[SZ]] %{{.+}} to i8* + // CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* + // CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* + // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CBPADDR1]] + // CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[CPADDR1]] // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] @@ -232,56 +232,58 @@ int foo(int n) { // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. - // CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* - // CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* - // CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR0:%.+]], + // CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR0:%.+]], + // CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8* - // CHECK-DAG: [[P1:%[^,]+]] = inttoptr i[[SZ]] [[VLA1]] to i8* - // CHECK-DAG: store i8* [[BP1]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P1]], i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CBPADDR1:%.+]], + // CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CPADDR1:%.+]], + // CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}} - // CHECK-DAG: store i8* inttoptr (i[[SZ]] 5 to i8*), i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CBPADDR2:%.+]], + // CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CPADDR2:%.+]], + // CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8* - // CHECK-DAG: [[P3:%[^,]+]] = inttoptr i[[SZ]] [[A_CVAL]] to i8* - // CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}} + // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CBPADDR3:%.+]], + // CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CPADDR3:%.+]], + // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* + // CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8* - // CHECK-DAG: [[P4:%[^,]+]] = bitcast [10 x float]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}} + // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CBPADDR4:%.+]], + // CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CPADDR4:%.+]], + // CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [10 x float]** + // CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [10 x float]** // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP5:%[^,]+]] = bitcast float* %{{.+}} to i8* - // CHECK-DAG: [[P5:%[^,]+]] = bitcast float* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP5]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P5]], i8** {{%[^,]+}} + // CHECK-DAG: store float* %{{.+}}, float** [[CBPADDR5:%.+]], + // CHECK-DAG: store float* %{{.+}}, float** [[CPADDR5:%.+]], + // CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to float** + // CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to float** // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8* - // CHECK-DAG: [[P6:%[^,]+]] = bitcast [5 x [10 x double]]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP6]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P6]], i8** {{%[^,]+}} + // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CBPADDR6:%.+]], + // CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CPADDR6:%.+]], + // CHECK-DAG: [[CBPADDR6]] = bitcast i8** {{%[^,]+}} to [5 x [10 x double]]** + // CHECK-DAG: [[CPADDR6]] = bitcast i8** {{%[^,]+}} to [5 x [10 x double]]** // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP7:%[^,]+]] = bitcast double* %{{.+}} to i8* - // CHECK-DAG: [[P7:%[^,]+]] = bitcast double* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP7]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P7]], i8** {{%[^,]+}} + // CHECK-DAG: store double* %{{.+}}, double** [[CBPADDR7:%.+]], + // CHECK-DAG: store double* %{{.+}}, double** [[CPADDR7:%.+]], + // CHECK-DAG: [[CBPADDR7]] = bitcast i8** {{%[^,]+}} to double** + // CHECK-DAG: [[CPADDR7]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* {{%[^,]+}} - // CHECK-DAG: [[BP8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8* - // CHECK-DAG: [[P8:%[^,]+]] = bitcast [[TT]]* %{{.+}} to i8* - // CHECK-DAG: store i8* [[BP8]], i8** {{%[^,]+}} - // CHECK-DAG: store i8* [[P8]], i8** {{%[^,]+}} + // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CBPADDR8:%.+]], + // CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CPADDR8:%.+]], + // CHECK-DAG: [[CBPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]** + // CHECK-DAG: [[CPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]** // CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* {{%[^,]+}} // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 @@ -550,32 +552,34 @@ int bar(int n){ // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. -// CHECK-DAG: [[BP0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* -// CHECK-DAG: [[P0:%[^,]+]] = inttoptr i[[SZ]] [[VLA0]] to i8* -// CHECK-DAG: store i8* [[BP0]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P0]], i8** {{%[^,]+}} +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR0:%.+]], +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR0:%.+]], +// CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}} -// CHECK-DAG: store i8* inttoptr (i[[SZ]] 2 to i8*), i8** {{%[^,]+}} +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR1:%.+]], +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR1:%.+]], +// CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: [[BP2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8* -// CHECK-DAG: [[P2:%[^,]+]] = inttoptr i[[SZ]] [[B_CVAL]] to i8* -// CHECK-DAG: store i8* [[BP2]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P2]], i8** {{%[^,]+}} +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR2:%.+]], +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR2:%.+]], +// CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: [[BP3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8* -// CHECK-DAG: [[P3:%[^,]+]] = bitcast [[S1]]* %{{.+}} to i8* -// CHECK-DAG: store i8* [[BP3]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P3]], i8** {{%[^,]+}} +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: [[BP4:%[^,]+]] = bitcast i16* %{{.+}} to i8* -// CHECK-DAG: [[P4:%[^,]+]] = bitcast i16* %{{.+}} to i8* -// CHECK-DAG: store i8* [[BP4]], i8** {{%[^,]+}} -// CHECK-DAG: store i8* [[P4]], i8** {{%[^,]+}} +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 @@ -600,29 +604,31 @@ int bar(int n){ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 0 -// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] -// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] -// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8* -// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8* +// CHECK-DAG: store i[[SZ]] [[VAL0:%.+]], i[[SZ]]* [[CBPADDR0:%.+]], +// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0:%.+]], +// CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 1 -// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] -// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] -// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8* -// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8* +// CHECK-DAG: store i[[SZ]] [[VAL1:%.+]], i[[SZ]]* [[CBPADDR1:%.+]], +// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1:%.+]], +// CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 2 // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 2 -// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]] -// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]] +// CHECK-DAG: store i[[SZ]] [[VAL2:%.+]], i[[SZ]]* [[CBPADDR2:%.+]], +// CHECK-DAG: store i[[SZ]] [[VAL2]], i[[SZ]]* [[CPADDR2:%.+]], +// CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BP]], i32 0, i32 3 // CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[P]], i32 0, i32 3 -// CHECK-DAG: store i8* [[BP3:%[^,]+]], i8** [[BPADDR3]] -// CHECK-DAG: store i8* [[P3:%[^,]+]], i8** [[PADDR3]] -// CHECK-DAG: [[BP3]] = bitcast [10 x i32]* %{{.+}} to i8* -// CHECK-DAG: [[P3]] = bitcast [10 x i32]* %{{.+}} to i8* +// CHECK-DAG: store [10 x i32]* %{{.+}}, [10 x i32]** [[CBPADDR3:%.+]], +// CHECK-DAG: store [10 x i32]* %{{.+}}, [10 x i32]** [[CPADDR3:%.+]], +// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [10 x i32]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [10 x i32]** // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] @@ -652,24 +658,24 @@ int bar(int n){ // CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 0 // CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 0 -// CHECK-DAG: store i8* [[BP0:%[^,]+]], i8** [[BPADDR0]] -// CHECK-DAG: store i8* [[P0:%[^,]+]], i8** [[PADDR0]] -// CHECK-DAG: [[BP0]] = inttoptr i[[SZ]] [[VAL0:%.+]] to i8* -// CHECK-DAG: [[P0]] = inttoptr i[[SZ]] [[VAL0]] to i8* +// CHECK-DAG: store i[[SZ]] [[VAL0:%.+]], i[[SZ]]* [[CBPADDR0:%.+]], +// CHECK-DAG: store i[[SZ]] [[VAL0]], i[[SZ]]* [[CPADDR0:%.+]], +// CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 1 // CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 1 -// CHECK-DAG: store i8* [[BP1:%[^,]+]], i8** [[BPADDR1]] -// CHECK-DAG: store i8* [[P1:%[^,]+]], i8** [[PADDR1]] -// CHECK-DAG: [[BP1]] = inttoptr i[[SZ]] [[VAL1:%.+]] to i8* -// CHECK-DAG: [[P1]] = inttoptr i[[SZ]] [[VAL1]] to i8* +// CHECK-DAG: store i[[SZ]] [[VAL1:%.+]], i[[SZ]]* [[CBPADDR1:%.+]], +// CHECK-DAG: store i[[SZ]] [[VAL1]], i[[SZ]]* [[CPADDR1:%.+]], +// CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* +// CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]* // CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[BP]], i32 0, i32 2 // CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[P]], i32 0, i32 2 -// CHECK-DAG: store i8* [[BP2:%[^,]+]], i8** [[BPADDR2]] -// CHECK-DAG: store i8* [[P2:%[^,]+]], i8** [[PADDR2]] -// CHECK-DAG: [[BP2]] = bitcast [10 x i32]* %{{.+}} to i8* -// CHECK-DAG: [[P2]] = bitcast [10 x i32]* %{{.+}} to i8* +// CHECK-DAG: store [10 x i32]* [[VAL2:%.+]], [10 x i32]** [[CBPADDR2:%.+]], +// CHECK-DAG: store [10 x i32]* [[VAL2]], [10 x i32]** [[CPADDR2:%.+]], +// CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to [10 x i32]** +// CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to [10 x i32]** // CHECK: store i32 [[RET]], i32* [[RHV:%.+]], align 4 // CHECK-NEXT: br label %[[IFEND:.+]] diff --git a/test/OpenMP/target_update_codegen.cpp b/test/OpenMP/target_update_codegen.cpp index f74ed4997537..f1e61a54c6e2 100644 --- a/test/OpenMP/target_update_codegen.cpp +++ b/test/OpenMP/target_update_codegen.cpp @@ -45,8 +45,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast ([100 x double]* @gc to i8*), i8** [[P0]] + // CK1-DAG: [[BPC0:%.+]] = bitcast i8** [[BP0]] to [100 x double]** + // CK1-DAG: [[PC0:%.+]] = bitcast i8** [[P0]] to [100 x double]** + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[BPC0]] + // CK1-DAG: store [100 x double]* @gc, [100 x double]** [[PC0]] // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 #pragma omp target update if(1+3-5) device(arg) from(gc) @@ -66,10 +68,10 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] - // CK1-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast i32* [[VAR0]] to i8* + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK1-DAG: store i32* [[VAL0:%[^,]+]], i32** [[CBP0]] + // CK1-DAG: store i32* [[VAL0]], i32** [[CP0]] // CK1: br label %[[IFEND:[^,]+]] // CK1: [[IFELSE]] @@ -91,11 +93,11 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] - // CK1-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to float** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float** + // CK1-DAG: store float* [[VAL0:%[^,]+]], float** [[CBP0]] + // CK1-DAG: store float* [[VAL0]], float** [[CP0]] // CK1-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]] - // CK1-DAG: [[CBPVAL0]] = bitcast float* [[VAR0:%.+]] to i8* - // CK1-DAG: [[CPVAL0]] = bitcast float* [[VAR0]] to i8* // CK1-DAG: [[CSVAL0]] = mul nuw i[[sz]] %{{[^,]+}}, 4 // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 // CK1-NOT: __tgt_target_data_end @@ -112,16 +114,19 @@ void foo(int arg) { // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK1-DAG: store i8* bitcast ([[ST]]* @gb to i8*), i8** [[BP0]] - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[P0]] + // CK1-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** + // CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** + // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]] + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]] // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK1-DAG: store i8* bitcast (double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1) to i8*), i8** [[BP1]] - // CK1-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] - // CK1-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%.+]] to i8* - // CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}double* [[SEC11:%[^,]+]], i{{.+}} 0 + // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** + // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CBP1]] + // CK1-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK1-DAG: store double* [[VAL1:%[^,]+]], double** [[CP1]] + // CK1-DAG: [[VAL1]] = getelementptr inbounds {{.+}}double* [[SEC11:%.+]], i{{.+}} 0 // CK1-DAG: [[SEC11]] = load double*, double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1 @@ -172,19 +177,19 @@ int bar(int arg){ // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 -// CK2-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]] -// CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]] -// CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8* -// CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%[^,]+]] to i8* +// CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** +// CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** +// CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]] +// CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK2-DAG: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]] -// CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]] -// CK2-DAG: [[CBPVAL1]] = bitcast double** [[SEC0]] to i8* -// CK2-DAG: [[CPVAL1]] = bitcast double* [[SEC1:%[^,]+]] to i8* +// CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** +// CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** +// CK2-DAG: store double** [[CBPVAL1:%[^,]+]], double*** [[CBP1]] +// CK2-DAG: store double* [[SEC1:%[^,]+]], double** [[CP1]] // CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1 // CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]], // CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 diff --git a/test/OpenMP/taskloop_ast_print.cpp b/test/OpenMP/taskloop_ast_print.cpp index d2fae3fe0f4f..36f90c95dd33 100644 --- a/test/OpenMP/taskloop_ast_print.cpp +++ b/test/OpenMP/taskloop_ast_print.cpp @@ -13,14 +13,14 @@ T tmain(T argc) { T b = argc, c, d, e, f, g; static T a; // CHECK: static T a; -#pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) - // CHECK-NEXT: #pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) +#pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) reduction(+:g) + // CHECK-NEXT: #pragma omp taskloop if(taskloop: argc > N) default(shared) untied priority(N) grainsize(N) reduction(+: g) for (int i = 0; i < 2; ++i) a = 2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; #pragma omp parallel -#pragma omp taskloop private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) shared(g) if (c) final(d) mergeable priority(f) nogroup num_tasks(N) +#pragma omp taskloop private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) shared(g) if (c) final(d) mergeable priority(f) nogroup num_tasks(N) reduction(min:a) for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) for (int j = 0; j < 2; ++j) @@ -33,7 +33,7 @@ T tmain(T argc) { for (int j = 0; j < 2; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp taskloop private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) shared(g) if(c) final(d) mergeable priority(f) nogroup num_tasks(N) + // CHECK-NEXT: #pragma omp taskloop private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) shared(g) if(c) final(d) mergeable priority(f) nogroup num_tasks(N) reduction(min: a) // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: for (int j = 0; j < 2; ++j) // CHECK-NEXT: for (int j = 0; j < 2; ++j) @@ -53,19 +53,19 @@ int main(int argc, char **argv) { int b = argc, c, d, e, f, g; static int a; // CHECK: static int a; -#pragma omp taskloop if(taskloop: a) default(none) shared(a) final(b) priority(5) nogroup num_tasks(argc) - // CHECK-NEXT: #pragma omp taskloop if(taskloop: a) default(none) shared(a) final(b) priority(5) nogroup num_tasks(argc) +#pragma omp taskloop if(taskloop: a) default(none) shared(a) final(b) priority(5) nogroup num_tasks(argc) reduction(*: g) + // CHECK-NEXT: #pragma omp taskloop if(taskloop: a) default(none) shared(a) final(b) priority(5) nogroup num_tasks(argc) reduction(*: g) for (int i = 0; i < 2; ++i) a = 2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; #pragma omp parallel -#pragma omp taskloop private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) shared(g) if(argc) mergeable priority(argc) grainsize(argc) +#pragma omp taskloop private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) shared(g) if(argc) mergeable priority(argc) grainsize(argc) reduction(max: a, e) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp taskloop private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) shared(g) if(argc) mergeable priority(argc) grainsize(argc) + // CHECK-NEXT: #pragma omp taskloop private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) shared(g) if(argc) mergeable priority(argc) grainsize(argc) reduction(max: a,e) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: foo(); diff --git a/test/OpenMP/taskloop_simd_ast_print.cpp b/test/OpenMP/taskloop_simd_ast_print.cpp index f16b470a3012..9bee8f7f93fd 100644 --- a/test/OpenMP/taskloop_simd_ast_print.cpp +++ b/test/OpenMP/taskloop_simd_ast_print.cpp @@ -14,14 +14,14 @@ T tmain(T argc) { T *ptr; static T a; // CHECK: static T a; -#pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) - // CHECK-NEXT: #pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) +#pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) reduction(+:g) + // CHECK-NEXT: #pragma omp taskloop simd if(taskloop: argc > N) default(shared) untied priority(N) safelen(N) linear(c) aligned(ptr) grainsize(N) reduction(+: g) for (int i = 0; i < 2; ++i) a = 2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; #pragma omp parallel -#pragma omp taskloop simd private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) shared(g) if (c) final(d) mergeable priority(f) simdlen(N) nogroup num_tasks(N) +#pragma omp taskloop simd private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) shared(g) if (c) final(d) mergeable priority(f) simdlen(N) nogroup num_tasks(N) reduction(min:a) for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) for (int j = 0; j < 2; ++j) @@ -34,7 +34,7 @@ T tmain(T argc) { for (int j = 0; j < 2; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp taskloop simd private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) shared(g) if(c) final(d) mergeable priority(f) simdlen(N) nogroup num_tasks(N) + // CHECK-NEXT: #pragma omp taskloop simd private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) shared(g) if(c) final(d) mergeable priority(f) simdlen(N) nogroup num_tasks(N) reduction(min: a) // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: for (int j = 0; j < 2; ++j) // CHECK-NEXT: for (int j = 0; j < 2; ++j) @@ -54,19 +54,19 @@ int main(int argc, char **argv) { int b = argc, c, d, e, f, g; static int a; // CHECK: static int a; -#pragma omp taskloop simd if(taskloop: a) default(none) shared(a) final(b) priority(5) safelen(8) linear(b), aligned(argv) nogroup num_tasks(argc) - // CHECK-NEXT: #pragma omp taskloop simd if(taskloop: a) default(none) shared(a) final(b) priority(5) safelen(8) linear(b) aligned(argv) nogroup num_tasks(argc) +#pragma omp taskloop simd if(taskloop: a) default(none) shared(a) final(b) priority(5) safelen(8) linear(b), aligned(argv) nogroup num_tasks(argc) reduction(*: g) + // CHECK-NEXT: #pragma omp taskloop simd if(taskloop: a) default(none) shared(a) final(b) priority(5) safelen(8) linear(b) aligned(argv) nogroup num_tasks(argc) reduction(*: g) for (int i = 0; i < 2; ++i) a = 2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; #pragma omp parallel -#pragma omp taskloop simd private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) shared(g) if(argc) mergeable priority(argc) simdlen(16) grainsize(argc) +#pragma omp taskloop simd private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) shared(g) if(argc) mergeable priority(argc) simdlen(16) grainsize(argc) reduction(max: a, e) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp taskloop simd private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) shared(g) if(argc) mergeable priority(argc) simdlen(16) grainsize(argc) + // CHECK-NEXT: #pragma omp taskloop simd private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) shared(g) if(argc) mergeable priority(argc) simdlen(16) grainsize(argc) reduction(max: a,e) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: foo(); diff --git a/test/PCH/attrs.c b/test/PCH/attrs.c index 3f34d4d00908..3bf660cf28e0 100644 --- a/test/PCH/attrs.c +++ b/test/PCH/attrs.c @@ -13,8 +13,9 @@ int g(int) __attribute__((abi_tag("foo", "bar", "baz"), no_sanitize("address", " #else +float f(float); double f(double); // expected-error{{overloadable}} - // expected-note@11{{previous overload}} + // expected-note@-2{{previous unmarked overload}} void h() { g(0); } #endif diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c index 43a050b14c06..721246aff3a7 100644 --- a/test/Preprocessor/aarch64-target-features.c +++ b/test/Preprocessor/aarch64-target-features.c @@ -71,8 +71,9 @@ // CHECK-NEON: __ARM_NEON 1 // CHECK-NEON: __ARM_NEON_FP 0xE -// RUN: %clang -target aarch64-none-eabi -march=armv8.1-a -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-V81A %s -// CHECK-V81A: __ARM_FEATURE_QRDMX 1 +// RUN: %clang -target aarch64-none-eabi -march=armv8.1-a -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-QRDMX %s +// RUN: %clang -target aarch64-none-eabi -march=armv8.2-a -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-QRDMX %s +// CHECK-QRDMX: __ARM_FEATURE_QRDMX 1 // RUN: %clang -target aarch64 -march=arm64 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-ARCH-NOT-ACCEPT %s // RUN: %clang -target aarch64 -march=aarch64 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-ARCH-NOT-ACCEPT %s diff --git a/test/Preprocessor/arm-target-features.c b/test/Preprocessor/arm-target-features.c index 81dab475fc9d..b206e1cf36fd 100644 --- a/test/Preprocessor/arm-target-features.c +++ b/test/Preprocessor/arm-target-features.c @@ -441,4 +441,5 @@ // CHECK-V82A: #define __ARM_ARCH 8 // CHECK-V82A: #define __ARM_ARCH_8_2A__ 1 // CHECK-V82A: #define __ARM_ARCH_PROFILE 'A' +// CHECK-V82A: #define __ARM_FEATURE_QRDMX 1 // CHECK-V82A: #define __ARM_FP 0xE diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c index 08f4d2573f40..da4c5d03574b 100644 --- a/test/Preprocessor/predefined-arch-macros.c +++ b/test/Preprocessor/predefined-arch-macros.c @@ -986,6 +986,81 @@ // CHECK_ATOM_M64: #define __x86_64 1 // CHECK_ATOM_M64: #define __x86_64__ 1 // +// RUN: %clang -march=goldmont -m32 -E -dM %s -o - 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: | FileCheck %s -check-prefix=CHECK_GLM_M32 +// CHECK_GLM_M32: #define __AES__ 1 +// CHECK_GLM_M32: #define __CLFLUSHOPT__ 1 +// CHECK_GLM_M32: #define __FXSR__ 1 +// CHECK_GLM_M32: #define __MMX__ 1 +// CHECK_GLM_M32: #define __MPX__ 1 +// CHECK_GLM_M32: #define __PCLMUL__ 1 +// CHECK_GLM_M32: #define __POPCNT__ 1 +// CHECK_GLM_M32: #define __RDRND__ 1 +// CHECK_GLM_M32: #define __RDSEED__ 1 +// CHECK_GLM_M32: #define __SHA__ 1 +// CHECK_GLM_M32: #define __SSE2__ 1 +// CHECK_GLM_M32: #define __SSE3__ 1 +// CHECK_GLM_M32: #define __SSE4_1__ 1 +// CHECK_GLM_M32: #define __SSE4_2__ 1 +// CHECK_GLM_M32: #define __SSE_MATH__ 1 +// CHECK_GLM_M32: #define __SSE__ 1 +// CHECK_GLM_M32: #define __SSSE3__ 1 +// CHECK_GLM_M32: #define __XSAVEC__ 1 +// CHECK_GLM_M32: #define __XSAVEOPT__ 1 +// CHECK_GLM_M32: #define __XSAVES__ 1 +// CHECK_GLM_M32: #define __XSAVE__ 1 +// CHECK_GLM_M32: #define __clang__ 1 +// CHECK_GLM_M32: #define __goldmont 1 +// CHECK_GLM_M32: #define __goldmont__ 1 +// CHECK_GLM_M32: #define __i386 1 +// CHECK_GLM_M32: #define __i386__ 1 +// CHECK_GLM_M32: #define __linux 1 +// CHECK_GLM_M32: #define __linux__ 1 +// CHECK_GLM_M32: #define __llvm__ 1 +// CHECK_GLM_M32: #define __tune_goldmont__ 1 +// CHECK_GLM_M32: #define __unix 1 +// CHECK_GLM_M32: #define __unix__ 1 +// CHECK_GLM_M32: #define i386 1 +// CHECK_GLM_M32: #define linux 1 +// CHECK_GLM_M32: #define unix 1 +// +// RUN: %clang -march=goldmont -m64 -E -dM %s -o - 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: | FileCheck %s -check-prefix=CHECK_GLM_M64 +// CHECK_GLM_M64: #define __AES__ 1 +// CHECK_GLM_M64: #define __CLFLUSHOPT__ 1 +// CHECK_GLM_M64: #define __FXSR__ 1 +// CHECK_GLM_M64: #define __MMX__ 1 +// CHECK_GLM_M64: #define __MPX__ 1 +// CHECK_GLM_M64: #define __PCLMUL__ 1 +// CHECK_GLM_M64: #define __POPCNT__ 1 +// CHECK_GLM_M64: #define __RDRND__ 1 +// CHECK_GLM_M64: #define __RDSEED__ 1 +// CHECK_GLM_M64: #define __SSE2__ 1 +// CHECK_GLM_M64: #define __SSE3__ 1 +// CHECK_GLM_M64: #define __SSE4_1__ 1 +// CHECK_GLM_M64: #define __SSE4_2__ 1 +// CHECK_GLM_M64: #define __SSE__ 1 +// CHECK_GLM_M64: #define __SSSE3__ 1 +// CHECK_GLM_M64: #define __XSAVEC__ 1 +// CHECK_GLM_M64: #define __XSAVEOPT__ 1 +// CHECK_GLM_M64: #define __XSAVES__ 1 +// CHECK_GLM_M64: #define __XSAVE__ 1 +// CHECK_GLM_M64: #define __gnu_linux__ 1 +// CHECK_GLM_M64: #define __goldmont 1 +// CHECK_GLM_M64: #define __goldmont__ 1 +// CHECK_GLM_M64: #define __linux 1 +// CHECK_GLM_M64: #define __linux__ 1 +// CHECK_GLM_M64: #define __llvm__ 1 +// CHECK_GLM_M64: #define __tune_goldmont__ 1 +// CHECK_GLM_M64: #define __unix 1 +// CHECK_GLM_M64: #define __unix__ 1 +// CHECK_GLM_M64: #define __x86_64 1 +// CHECK_GLM_M64: #define __x86_64__ 1 +// CHECK_GLM_M64: #define linux 1 +// CHECK_GLM_M64: #define unix 1 +// // RUN: %clang -march=slm -m32 -E -dM %s -o - 2>&1 \ // RUN: -target i386-unknown-linux \ // RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M32 diff --git a/test/Preprocessor/predefined-macros.c b/test/Preprocessor/predefined-macros.c index 7385cd2c93ef..662a712d6477 100644 --- a/test/Preprocessor/predefined-macros.c +++ b/test/Preprocessor/predefined-macros.c @@ -185,3 +185,9 @@ // CHECK-CL20-NOT: #define __FAST_RELAXED_MATH__ 1 // CHECK-FRM: #define __FAST_RELAXED_MATH__ 1 +// RUN: %clang_cc1 -triple aarch64-windows %s -E -dM -o - -x cl \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-WIN + +// CHECK-ARM64-WIN: #define _M_ARM64 1 +// CHECK-ARM64-WIN: #define _WIN32 1 +// CHECK-ARM64-WIN: #define _WIN64 1 diff --git a/test/Profile/Inputs/cxx-missing-bodies.proftext b/test/Profile/Inputs/cxx-missing-bodies.proftext new file mode 100644 index 000000000000..c07f297f74d1 --- /dev/null +++ b/test/Profile/Inputs/cxx-missing-bodies.proftext @@ -0,0 +1,9 @@ +??_GA@@UAEPAXI@Z +1 +1 +1 + +??_DA@@QAEXXZ +1 +1 +1 diff --git a/test/Profile/cxx-missing-bodies.cpp b/test/Profile/cxx-missing-bodies.cpp new file mode 100644 index 000000000000..fe926b3b2182 --- /dev/null +++ b/test/Profile/cxx-missing-bodies.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -emit-llvm %s -std=c++11 -S -emit-llvm -o - -triple=i386-pc-win32 -fno-rtti -fprofile-instrument=clang | FileCheck %s --check-prefix=GEN +// +// Don't crash when presented profile data for functions without bodies: +// RUN: llvm-profdata merge %S/Inputs/cxx-missing-bodies.proftext -o %t.profdata +// RUN: %clang_cc1 -emit-llvm %s -std=c++11 -S -emit-llvm -o /dev/null -triple=i386-pc-win32 -fno-rtti -fprofile-instrument-use-path=%t.profdata -w + +// GEN-NOT: __profn{{.*}}??_GA@@UAEPAXI@Z +// GEN-NOT: __profn{{.*}}??_DA@@QAEXXZ + +struct A { + virtual ~A(); +}; +struct B : A { + virtual ~B(); +}; + +B::~B() {} + +void foo() { + B c; +} diff --git a/test/Profile/cxx-structors.cpp b/test/Profile/cxx-structors.cpp index 8e0fac163d97..1af01babf3b1 100644 --- a/test/Profile/cxx-structors.cpp +++ b/test/Profile/cxx-structors.cpp @@ -33,7 +33,7 @@ Baz baz; Baz baz2(1); Quux qux("fi", "fo", "fum"); -// Profile data for complete constructors and destructors must absent. +// Profile data for complete constructors and destructors must be absent. // INSTR: @__profc__ZN3BazC1Ev = // INSTR: @__profc__ZN3BazC1Ei = diff --git a/test/Sema/diagnose_if.c b/test/Sema/diagnose_if.c index 27689f49b431..38a3307d924a 100644 --- a/test/Sema/diagnose_if.c +++ b/test/Sema/diagnose_if.c @@ -153,3 +153,7 @@ void runAlwaysWarnWithArg(int a) { // Test that diagnose_if warnings generated in system headers are not ignored. #include "Inputs/diagnose-if-warn-system-header.h" + +// Bug: we would complain about `a` being undeclared if this was spelled +// __diagnose_if__. +void underbarName(int a) __attribute__((__diagnose_if__(a, "", "warning"))); diff --git a/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c index 62ee33e3d181..44c2629ebf7b 100644 --- a/test/Sema/integer-overflow.c +++ b/test/Sema/integer-overflow.c @@ -152,13 +152,7 @@ uint64_t check_integer_overflows(int i) { uint64_t b2 = b[4608 * 1024 * 1024] + 1; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} - int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024); - -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - int j2 = -(4608 * 1024 * 1024); - -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - uint64_t j3 = b[4608 * 1024 * 1024]; + (void)((i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)) + 1); // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c index be9b862f2934..4bdec85f9ca9 100644 --- a/test/Sema/overloadable.c +++ b/test/Sema/overloadable.c @@ -3,12 +3,15 @@ int var __attribute__((overloadable)); // expected-error{{'overloadable' attribute only applies to functions}} void params(void) __attribute__((overloadable(12))); // expected-error {{'overloadable' attribute takes no arguments}} -int *f(int) __attribute__((overloadable)); // expected-note 2{{previous overload of function is here}} -float *f(float); // expected-error{{overloaded function 'f' must have the 'overloadable' attribute}} +int *f(int) __attribute__((overloadable)); // expected-note{{previous overload of function is here}} +float *f(float); int *f(int); // expected-error{{redeclaration of 'f' must have the 'overloadable' attribute}} \ // expected-note{{previous declaration is here}} double *f(double) __attribute__((overloadable)); // okay, new +// Ensure we don't complain about overloadable on implicitly declared functions. +int isdigit(int) __attribute__((overloadable)); + void test_f(int iv, float fv, double dv) { int *ip = f(iv); float *fp = f(fv); @@ -71,19 +74,19 @@ void test() { f1(); } -void before_local_1(int) __attribute__((overloadable)); // expected-note {{here}} +void before_local_1(int) __attribute__((overloadable)); void before_local_2(int); // expected-note {{here}} void before_local_3(int) __attribute__((overloadable)); void local() { - void before_local_1(char); // expected-error {{must have the 'overloadable' attribute}} - void before_local_2(char) __attribute__((overloadable)); // expected-error {{conflicting types}} + void before_local_1(char); + void before_local_2(char); // expected-error {{conflicting types}} void before_local_3(char) __attribute__((overloadable)); - void after_local_1(char); // expected-note {{here}} - void after_local_2(char) __attribute__((overloadable)); // expected-note {{here}} + void after_local_1(char); + void after_local_2(char) __attribute__((overloadable)); void after_local_3(char) __attribute__((overloadable)); } -void after_local_1(int) __attribute__((overloadable)); // expected-error {{conflicting types}} -void after_local_2(int); // expected-error {{must have the 'overloadable' attribute}} +void after_local_1(int) __attribute__((overloadable)); +void after_local_2(int); void after_local_3(int) __attribute__((overloadable)); // Make sure we allow C-specific conversions in C. @@ -152,6 +155,85 @@ void dropping_qualifiers_is_incompatible() { foo(vcharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@-4{{candidate function}} expected-note@-3{{candidate function}} } +void overloadable_with_global() { + void wg_foo(void) __attribute__((overloadable)); // expected-note{{previous}} + void wg_foo(int) __attribute__((overloadable)); +} + +int wg_foo; // expected-error{{redefinition of 'wg_foo' as different kind of symbol}} + +#if !__has_extension(overloadable_unmarked) +#error "We should have unmarked overload support" +#endif + +void to_foo0(int); +void to_foo0(double) __attribute__((overloadable)); // expected-note{{previous overload}} +void to_foo0(int); +void to_foo0(double); // expected-error{{must have the 'overloadable' attribute}} +void to_foo0(int); + +void to_foo1(int) __attribute__((overloadable)); // expected-note 2{{previous overload}} +void to_foo1(double); +void to_foo1(int); // expected-error{{must have the 'overloadable' attribute}} +void to_foo1(double); +void to_foo1(int); // expected-error{{must have the 'overloadable' attribute}} + +void to_foo2(int); // expected-note{{previous unmarked overload}} +void to_foo2(double) __attribute__((overloadable)); // expected-note 2{{previous overload}} +void to_foo2(int) __attribute__((overloadable)); // expected-error {{must not have the 'overloadable' attribute}} +void to_foo2(double); // expected-error{{must have the 'overloadable' attribute}} +void to_foo2(int); +void to_foo2(double); // expected-error{{must have the 'overloadable' attribute}} +void to_foo2(int); + +void to_foo3(int); +void to_foo3(double) __attribute__((overloadable)); // expected-note{{previous overload}} +void to_foo3(int); +void to_foo3(double); // expected-error{{must have the 'overloadable' attribute}} + +void to_foo4(int) __attribute__((overloadable)); // expected-note{{previous overload}} +void to_foo4(int); // expected-error{{must have the 'overloadable' attribute}} +void to_foo4(double) __attribute__((overloadable)); + +void to_foo5(int); +void to_foo5(int); // expected-note 3{{previous unmarked overload}} +void to_foo5(float) __attribute__((overloadable)); +void to_foo5(double); // expected-error{{at most one overload for a given name may lack the 'overloadable' attribute}} +void to_foo5(float) __attribute__((overloadable)); +void to_foo5(short); // expected-error{{at most one overload for a given name may lack the 'overloadable' attribute}} +void to_foo5(long); // expected-error{{at most one overload for a given name may lack the 'overloadable' attribute}} +void to_foo5(double) __attribute__((overloadable)); + +void to_foo6(int) __attribute__((enable_if(1, ""), overloadable)); // expected-note{{previous overload}} +void to_foo6(int) __attribute__((enable_if(1, ""))); // expected-error{{must have the 'overloadable' attribute}} +void to_foo6(int) __attribute__((enable_if(1, ""), overloadable)); + +void to_foo7(int) __attribute__((enable_if(1, ""))); // expected-note{{previous unmarked overload}} +void to_foo7(int) __attribute__((enable_if(1, ""), overloadable)); // expected-error{{must not have the 'overloadable' attribute}} +void to_foo7(int) __attribute__((enable_if(1, ""))); + +void to_foo8(char *__attribute__((pass_object_size(0)))) + __attribute__((enable_if(1, ""))); +void to_foo8(char *__attribute__((pass_object_size(0)))) + __attribute__((overloadable)); + +void to_foo9(int); // expected-note{{previous unmarked overload}} +// FIXME: It would be nice if we did better with the "previous unmarked +// overload" diag. +void to_foo9(int) __attribute__((overloadable)); // expected-error{{must not have the 'overloadable' attribute}} expected-note{{previous declaration}} expected-note{{previous unmarked overload}} +void to_foo9(float); // expected-error{{conflicting types for 'to_foo9'}} +void to_foo9(float) __attribute__((overloadable)); +void to_foo9(double); // expected-error{{at most one overload for a given name may lack the 'overloadable' attribute}} +void to_foo9(double) __attribute__((overloadable)); + +void to_foo10(int) __attribute__((overloadable)); +void to_foo10(double); // expected-note{{previous unmarked overload}} +// no "note: previous redecl" if no previous decl has `overloadable` +// spelled out +void to_foo10(float); // expected-error{{at most one overload for a given name may lack the 'overloadable' attribute}} +void to_foo10(float); // expected-error{{must have the 'overloadable' attribute}} +void to_foo10(float); // expected-error{{must have the 'overloadable' attribute}} + // Bug: we used to treat `__typeof__(foo)` as though it was `__typeof__(&foo)` // if `foo` was overloaded with only one function that could have its address // taken. diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 4abbc8e92847..3fda2d0a7fd0 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -608,7 +608,7 @@ namespace DependentValues { struct I { int n; typedef I V[10]; }; I::V x, y; -int g(); +int g(); // expected-note {{declared here}} template<bool B, typename T> struct S : T { int k; void f() { @@ -616,13 +616,23 @@ template<bool B, typename T> struct S : T { I &i = cells[k]; switch (i.n) {} - // FIXME: We should be able to diagnose this. - constexpr int n = g(); + constexpr int n = g(); // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr function 'g'}} constexpr int m = this->g(); // ok, could be constexpr } }; +extern const int n; +template<typename T> void f() { + // This is ill-formed, because a hypothetical instantiation at the point of + // template definition would be ill-formed due to a construct that does not + // depend on a template parameter. + constexpr int k = n; // expected-error {{must be initialized by a constant expression}} +} +// It doesn't matter that the instantiation could later become valid: +constexpr int n = 4; +template void f<int>(); + } namespace Class { diff --git a/test/SemaCXX/eval-crashes.cpp b/test/SemaCXX/eval-crashes.cpp new file mode 100644 index 000000000000..23946845d8ed --- /dev/null +++ b/test/SemaCXX/eval-crashes.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +namespace pr32864_0 { + struct transfer_t { + void *fctx; + }; + template <typename Ctx> class record { + void run() { + transfer_t t; + Ctx from{t.fctx}; + } + }; +} + +namespace pr33140_0a { + struct S { + constexpr S(const int &a = 0) {} + }; + void foo(void) { S s[2] = {}; } +} + +namespace pr33140_0b { + bool bar(float const &f = 0); + bool foo() { return bar() && bar(); } +} + +namespace pr33140_2 { + // FIXME: The declaration of 'b' below should lifetime-extend two int + // temporaries, invalidating this warning to some extent. + struct A { int &&r = 0; }; // expected-warning {{binding reference member 'r' to a temporary}} expected-note {{here}} + struct B { A x, y; }; + B b = {}; +} + +namespace pr33140_3 { + typedef struct Y { unsigned int c; } Y_t; + struct X { + Y_t a; + }; + struct X foo[2] = {[0 ... 1] = {.a = (Y_t){.c = 0}}}; +} + +namespace pr33140_6 { + struct Y { unsigned int c; }; + struct X { struct Y *p; }; + int f() { + // FIXME: This causes clang to crash. + //return (struct X[2]){ [0 ... 1] = { .p = &(struct Y&)(struct Y&&)(struct Y){0} } }[0].p->c; + return 0; + } +} + +namespace pr33140_10 { + int a(const int &n = 0); + bool b() { return a() == a(); } +} diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 8a994f01ba1a..5879a77dd5a8 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1447,7 +1447,9 @@ void has_trivial_default_constructor() { { int arr[T(__has_trivial_constructor(const Int))]; } { int arr[T(__has_trivial_constructor(AllDefaulted))]; } { int arr[T(__has_trivial_constructor(AllDeleted))]; } + { int arr[T(__has_trivial_constructor(ACompleteType[]))]; } + { int arr[F(__has_trivial_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_constructor(HasCons))]; } { int arr[F(__has_trivial_constructor(HasRef))]; } { int arr[F(__has_trivial_constructor(HasCopy))]; } @@ -1478,7 +1480,9 @@ void has_trivial_move_constructor() { { int arr[T(__has_trivial_move_constructor(HasCons))]; } { int arr[T(__has_trivial_move_constructor(HasStaticMemberMoveCtor))]; } { int arr[T(__has_trivial_move_constructor(AllDeleted))]; } - + { int arr[T(__has_trivial_move_constructor(ACompleteType[]))]; } + + { int arr[F(__has_trivial_move_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_move_constructor(HasVirt))]; } { int arr[F(__has_trivial_move_constructor(DerivesVirt))]; } { int arr[F(__has_trivial_move_constructor(HasMoveCtor))]; } @@ -1508,7 +1512,9 @@ void has_trivial_copy_constructor() { { int arr[T(__has_trivial_copy(AllDeleted))]; } { int arr[T(__has_trivial_copy(DerivesAr))]; } { int arr[T(__has_trivial_copy(DerivesHasRef))]; } + { int arr[T(__has_trivial_copy(ACompleteType[]))]; } + { int arr[F(__has_trivial_copy(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_copy(HasCopy))]; } { int arr[F(__has_trivial_copy(HasTemplateCons))]; } { int arr[F(__has_trivial_copy(VirtAr))]; } @@ -1536,7 +1542,9 @@ void has_trivial_copy_assignment() { { int arr[T(__has_trivial_assign(AllDeleted))]; } { int arr[T(__has_trivial_assign(DerivesAr))]; } { int arr[T(__has_trivial_assign(DerivesHasRef))]; } + { int arr[T(__has_trivial_assign(ACompleteType[]))]; } + { int arr[F(__has_trivial_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_assign(IntRef))]; } { int arr[F(__has_trivial_assign(HasCopyAssign))]; } { int arr[F(__has_trivial_assign(const Int))]; } @@ -1572,8 +1580,10 @@ void has_trivial_destructor() { { int arr[T(__has_trivial_destructor(AllDefaulted))]; } { int arr[T(__has_trivial_destructor(AllDeleted))]; } { int arr[T(__has_trivial_destructor(DerivesHasRef))]; } + { int arr[T(__has_trivial_destructor(ACompleteType[]))]; } { int arr[F(__has_trivial_destructor(HasDest))]; } + { int arr[F(__has_trivial_destructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_destructor(void))]; } { int arr[F(__has_trivial_destructor(cvoid))]; } { int arr[F(__has_trivial_destructor(AllPrivate))]; } @@ -1625,7 +1635,9 @@ void has_nothrow_assign() { { int arr[T(__has_nothrow_assign(AllPrivate))]; } { int arr[T(__has_nothrow_assign(UsingAssign))]; } { int arr[T(__has_nothrow_assign(DerivesAr))]; } + { int arr[T(__has_nothrow_assign(ACompleteType[]))]; } + { int arr[F(__has_nothrow_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_nothrow_assign(IntRef))]; } { int arr[F(__has_nothrow_assign(HasCopyAssign))]; } { int arr[F(__has_nothrow_assign(HasMultipleCopyAssign))]; } @@ -1650,8 +1662,9 @@ void has_nothrow_move_assign() { { int arr[T(__has_nothrow_move_assign(HasMemberNoThrowMoveAssign))]; } { int arr[T(__has_nothrow_move_assign(HasMemberNoExceptNoThrowMoveAssign))]; } { int arr[T(__has_nothrow_move_assign(AllDeleted))]; } + { int arr[T(__has_nothrow_move_assign(ACompleteType[]))]; } - + { int arr[F(__has_nothrow_move_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_nothrow_move_assign(HasThrowMoveAssign))]; } { int arr[F(__has_nothrow_move_assign(HasNoExceptFalseMoveAssign))]; } { int arr[F(__has_nothrow_move_assign(HasMemberThrowMoveAssign))]; } @@ -1683,7 +1696,9 @@ void has_trivial_move_assign() { { int arr[T(__has_trivial_move_assign(Int))]; } { int arr[T(__has_trivial_move_assign(HasStaticMemberMoveAssign))]; } { int arr[T(__has_trivial_move_assign(AllDeleted))]; } + { int arr[T(__has_trivial_move_assign(ACompleteType[]))]; } + { int arr[F(__has_trivial_move_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_move_assign(HasVirt))]; } { int arr[F(__has_trivial_move_assign(DerivesVirt))]; } { int arr[F(__has_trivial_move_assign(HasMoveAssign))]; } @@ -1717,7 +1732,9 @@ void has_nothrow_copy() { { int arr[T(__has_nothrow_copy(HasTemplateCons))]; } { int arr[T(__has_nothrow_copy(AllPrivate))]; } { int arr[T(__has_nothrow_copy(DerivesAr))]; } + { int arr[T(__has_nothrow_copy(ACompleteType[]))]; } + { int arr[F(__has_nothrow_copy(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_nothrow_copy(HasCopy))]; } { int arr[F(__has_nothrow_copy(HasMultipleCopy))]; } { int arr[F(__has_nothrow_copy(VirtAr))]; } @@ -1743,7 +1760,9 @@ void has_nothrow_constructor() { { int arr[T(__has_nothrow_constructor(HasVirtDest))]; } // { int arr[T(__has_nothrow_constructor(VirtAr))]; } // not implemented { int arr[T(__has_nothrow_constructor(AllPrivate))]; } + { int arr[T(__has_nothrow_constructor(ACompleteType[]))]; } + { int arr[F(__has_nothrow_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_nothrow_constructor(HasCons))]; } { int arr[F(__has_nothrow_constructor(HasRef))]; } { int arr[F(__has_nothrow_constructor(HasCopy))]; } @@ -1779,7 +1798,9 @@ void has_virtual_destructor() { { int arr[F(__has_virtual_destructor(HasMoveAssign))]; } { int arr[F(__has_virtual_destructor(IntRef))]; } { int arr[F(__has_virtual_destructor(VirtAr))]; } + { int arr[F(__has_virtual_destructor(ACompleteType[]))]; } + { int arr[F(__has_virtual_destructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[T(__has_virtual_destructor(HasVirtDest))]; } { int arr[T(__has_virtual_destructor(DerivedVirtDest))]; } { int arr[F(__has_virtual_destructor(VirtDestAr))]; } diff --git a/test/SemaCXX/unavailable_aligned_allocation.cpp b/test/SemaCXX/unavailable_aligned_allocation.cpp new file mode 100644 index 000000000000..2ae5d2e2c704 --- /dev/null +++ b/test/SemaCXX/unavailable_aligned_allocation.cpp @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -faligned-allocation -faligned-alloc-unavailable -std=c++14 -verify %s + +namespace std { + typedef decltype(sizeof(0)) size_t; + enum class align_val_t : std::size_t {}; + struct nothrow_t {}; + nothrow_t nothrow; +} + +void *operator new(std::size_t __sz, const std::nothrow_t&) noexcept; +void *operator new[](std::size_t __sz, const std::nothrow_t&) noexcept; + +void *operator new(std::size_t __sz, std::align_val_t, const std::nothrow_t&) noexcept; +void *operator new[](std::size_t __sz, std::align_val_t, const std::nothrow_t&) noexcept; +void operator delete(void *, std::align_val_t, const std::nothrow_t&); +void operator delete[](void *, std::align_val_t, const std::nothrow_t&); +void operator delete(void*, std::size_t, std::align_val_t) noexcept; +void operator delete[](void*, std::size_t, std::align_val_t) noexcept; + +void *operator new(std::size_t, std::align_val_t, long long); + +struct alignas(256) OveralignedS { + int x[16]; +}; + +struct S { + int x[16]; +}; + +void test() { + auto *p = new S; + delete p; + p = new (std::nothrow) S; + + auto *pa = new S[4]; + delete[] pa; + pa = new (std::nothrow) S[4]; +} + +void testOveraligned() { + auto *p = new OveralignedS; + p = new ((std::align_val_t)8) OveralignedS; + delete p; + p = new (std::nothrow) OveralignedS; + + auto *pa = new OveralignedS[4]; + pa = new ((std::align_val_t)8) OveralignedS[4]; + delete[] pa; + pa = new (std::nothrow) OveralignedS[4]; + // No error here since it is not calling a replaceable allocation function. + p = new ((std::align_val_t)8, 10LL) OveralignedS; +} + +#ifdef NO_ERRORS +// expected-no-diagnostics +#else +// expected-error@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' possibly unavailable on}} +// expected-note@-17 {{if you supply your own aligned allocation functions}} +// expected-error@-18 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' possibly unavailable on}} +// expected-note@-19 {{if you supply your own aligned allocation functions}} + +// expected-error@-20 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' possibly unavailable on}} +// expected-note@-21 {{if you supply your own aligned allocation functions}} +// expected-error@-22 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' possibly unavailable on}} +// expected-note@-23 {{if you supply your own aligned allocation functions}} + +// expected-error@-24 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' possibly unavailable on}} +// expected-note@-25 {{if you supply your own aligned allocation functions}} + +// expected-error@-26 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' possibly unavailable on}} +// expected-note@-27 {{if you supply your own aligned allocation functions}} +// expected-error@-28 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' possibly unavailable on}} +// expected-note@-29 {{if you supply your own aligned allocation functions}} + +// expected-error@-29 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' possibly unavailable on}} +// expected-note@-30 {{if you supply your own aligned allocation functions}} +// expected-error@-31 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' possibly unavailable on}} +// expected-note@-32 {{if you supply your own aligned allocation functions}} + +// expected-error@-33 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' possibly unavailable on}} +// expected-note@-34 {{if you supply your own aligned allocation functions}} +// expected-error@-35 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' possibly unavailable on}} +// expected-note@-36 {{if you supply your own aligned allocation functions}} + +// expected-error@-37 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' possibly unavailable on}} +// expected-note@-38 {{if you supply your own aligned allocation functions}} + +// expected-error@-39 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' possibly unavailable on}} +// expected-note@-40 {{if you supply your own aligned allocation functions}} +// expected-error@-41 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' possibly unavailable on}} +// expected-note@-42 {{if you supply your own aligned allocation functions}} + +#endif + +// No errors if user-defined aligned allocation functions are available. +void *operator new(std::size_t __sz, std::align_val_t) { + static char array[256]; + return &array; +} + +void operator delete(void *p, std::align_val_t) { +} + +void testOveraligned2() { + auto p = new ((std::align_val_t)8) OveralignedS; + delete p; +} diff --git a/test/SemaCXX/warn-throw-out-noexcept-func.cpp b/test/SemaCXX/warn-throw-out-noexcept-func.cpp index dfd1ff9065ab..fc2919a1e327 100644 --- a/test/SemaCXX/warn-throw-out-noexcept-func.cpp +++ b/test/SemaCXX/warn-throw-out-noexcept-func.cpp @@ -253,6 +253,43 @@ void with_try_block1() noexcept try { //expected-note {{non-throwing function de } catch (char *) { } +namespace derived { +struct B {}; +struct D: B {}; +void goodPlain() noexcept { + try { + throw D(); + } catch (B) {} +} +void goodReference() noexcept { + try { + throw D(); + } catch (B &) {} +} +void goodPointer() noexcept { + D d; + try { + throw &d; + } catch (B *) {} +} +void badPlain() noexcept { // expected-note {{non-throwing function declare here}} + try { + throw B(); // expected-warning {{'badPlain' has a non-throwing exception specification but can still throw, resulting in unexpected program termination}} + } catch (D) {} +} +void badReference() noexcept { // expected-note {{non-throwing function declare here}} + try { + throw B(); // expected-warning {{'badReference' has a non-throwing exception specification but can still throw, resulting in unexpected program termination}} + } catch (D &) {} +} +void badPointer() noexcept { // expected-note {{non-throwing function declare here}} + B b; + try { + throw &b; // expected-warning {{'badPointer' has a non-throwing exception specification but can still throw, resulting in unexpected program termination}} + } catch (D *) {} +} +} + int main() { R1_ShouldDiag<int> o; //expected-note {{in instantiation of member function}} S1_ShouldDiag<int> b; //expected-note {{in instantiation of member function}} diff --git a/test/SemaOpenCL/extension-begin.cl b/test/SemaOpenCL/extension-begin.cl index 3393458a893a..92ea88143233 100644 --- a/test/SemaOpenCL/extension-begin.cl +++ b/test/SemaOpenCL/extension-begin.cl @@ -46,7 +46,7 @@ void test_f2(void) { const struct A test_A_local; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}} TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 'struct A') requires my_ext extension to be enabled}} PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}} - f(); // expected-error {{use of declaration requires my_ext extension to be enabled}} + f(); // expected-error {{use of declaration 'f' requires my_ext extension to be enabled}} g(0); // expected-error {{no matching function for call to 'g'}} // expected-note@-26 {{candidate disabled due to OpenCL extension}} // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}} diff --git a/test/SemaTemplate/destructor-template.cpp b/test/SemaTemplate/destructor-template.cpp index 853ba492f8e7..6570b6456406 100644 --- a/test/SemaTemplate/destructor-template.cpp +++ b/test/SemaTemplate/destructor-template.cpp @@ -86,3 +86,9 @@ namespace PR16852 { template<typename T> decltype(S<T>().~S()) f(); // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} void g() { f(); } // expected-error {{no matching function for call to 'f'}} } + +class PR33189 +{ + template <class T> + ~PR33189() { } // expected-error{{destructor cannot be declared as a template}} +}; diff --git a/test/clang-rename/ClassAsTemplateArgument.cpp b/test/clang-rename/ClassAsTemplateArgument.cpp new file mode 100644 index 000000000000..2e09a5b529e7 --- /dev/null +++ b/test/clang-rename/ClassAsTemplateArgument.cpp @@ -0,0 +1,21 @@ +class Foo /* Test 1 */ {}; // CHECK: class Bar /* Test 1 */ {}; + +template <typename T> +void func() {} + +template <typename T> +class Baz {}; + +int main() { + func<Foo>(); // CHECK: func<Bar>(); + Baz<Foo> /* Test 2 */ obj; // CHECK: Baz<Bar> /* Test 2 */ obj; + return 0; +} + +// Test 1. +// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=215 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/ClassFindByName.cpp b/test/clang-rename/ClassFindByName.cpp new file mode 100644 index 000000000000..4430891ec4b1 --- /dev/null +++ b/test/clang-rename/ClassFindByName.cpp @@ -0,0 +1,10 @@ +class Foo { // CHECK: class Bar { +}; + +int main() { + Foo *Pointer = 0; // CHECK: Bar *Pointer = 0; + return 0; +} + +// Test 1. +// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s diff --git a/test/clang-rename/ClassSimpleRenaming.cpp b/test/clang-rename/ClassSimpleRenaming.cpp new file mode 100644 index 000000000000..086f55736cb7 --- /dev/null +++ b/test/clang-rename/ClassSimpleRenaming.cpp @@ -0,0 +1,14 @@ +class Foo /* Test 1 */ { // CHECK: class Bar /* Test 1 */ { +public: + void foo(int x); +}; + +void Foo::foo(int x) /* Test 2 */ {} // CHECK: void Bar::foo(int x) /* Test 2 */ {} + +// Test 1. +// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=109 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/ClassTestMulti.cpp b/test/clang-rename/ClassTestMulti.cpp new file mode 100644 index 000000000000..81e65c760652 --- /dev/null +++ b/test/clang-rename/ClassTestMulti.cpp @@ -0,0 +1,11 @@ +class Foo1 /* Offset 1 */ { // CHECK: class Bar1 /* Offset 1 */ { +}; + +class Foo2 /* Offset 2 */ { // CHECK: class Bar2 /* Offset 2 */ { +}; + +// Test 1. +// RUN: clang-rename -offset=6 -new-name=Bar1 -offset=76 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/ClassTestMultiByName.cpp b/test/clang-rename/ClassTestMultiByName.cpp new file mode 100644 index 000000000000..61b69a1bdf4c --- /dev/null +++ b/test/clang-rename/ClassTestMultiByName.cpp @@ -0,0 +1,8 @@ +class Foo1 { // CHECK: class Bar1 +}; + +class Foo2 { // CHECK: class Bar2 +}; + +// Test 1. +// RUN: clang-rename -qualified-name=Foo1 -new-name=Bar1 -qualified-name=Foo2 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s diff --git a/test/clang-rename/ComplexFunctionOverride.cpp b/test/clang-rename/ComplexFunctionOverride.cpp new file mode 100644 index 000000000000..ccf3a20e5400 --- /dev/null +++ b/test/clang-rename/ComplexFunctionOverride.cpp @@ -0,0 +1,47 @@ +struct A { + virtual void foo() {} /* Test 1 */ // CHECK: virtual void bar() {} +}; + +struct B : A { + void foo() override {} /* Test 2 */ // CHECK: void bar() override {} +}; + +struct C : B { + void foo() override {} /* Test 3 */ // CHECK: void bar() override {} +}; + +struct D : B { + void foo() override {} /* Test 4 */ // CHECK: void bar() override {} +}; + +struct E : D { + void foo() override {} /* Test 5 */ // CHECK: void bar() override {} +}; + +int main() { + A a; + a.foo(); // CHECK: a.bar(); + B b; + b.foo(); // CHECK: b.bar(); + C c; + c.foo(); // CHECK: c.bar(); + D d; + d.foo(); // CHECK: d.bar(); + E e; + e.foo(); // CHECK: e.bar(); + return 0; +} + +// Test 1. +// RUN: clang-rename -offset=26 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=109 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=201 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 4. +// RUN: clang-rename -offset=293 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 5. +// RUN: clang-rename -offset=385 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'foo.*' <file> diff --git a/test/clang-rename/ComplicatedClassType.cpp b/test/clang-rename/ComplicatedClassType.cpp new file mode 100644 index 000000000000..880195303127 --- /dev/null +++ b/test/clang-rename/ComplicatedClassType.cpp @@ -0,0 +1,63 @@ +// Forward declaration. +class Foo; /* Test 1 */ // CHECK: class Bar; /* Test 1 */ + +class Baz { + virtual int getValue() const = 0; +}; + +class Foo : public Baz { /* Test 2 */// CHECK: class Bar : public Baz { +public: + Foo(int value = 0) : x(value) {} // CHECK: Bar(int value = 0) : x(value) {} + + Foo &operator++(int) { // CHECK: Bar &operator++(int) { + x++; + return *this; + } + + bool operator<(Foo const &rhs) { // CHECK: bool operator<(Bar const &rhs) { + return this->x < rhs.x; + } + + int getValue() const { + return 0; + } + +private: + int x; +}; + +int main() { + Foo *Pointer = 0; // CHECK: Bar *Pointer = 0; + Foo Variable = Foo(10); // CHECK: Bar Variable = Bar(10); + for (Foo it; it < Variable; it++) { // CHECK: for (Bar it; it < Variable; it++) { + } + const Foo *C = new Foo(); // CHECK: const Bar *C = new Bar(); + const_cast<Foo *>(C)->getValue(); // CHECK: const_cast<Bar *>(C)->getValue(); + Foo foo; // CHECK: Bar foo; + const Baz &BazReference = foo; + const Baz *BazPointer = &foo; + dynamic_cast<const Foo &>(BazReference).getValue(); /* Test 3 */ // CHECK: dynamic_cast<const Bar &>(BazReference).getValue(); + dynamic_cast<const Foo *>(BazPointer)->getValue(); /* Test 4 */ // CHECK: dynamic_cast<const Bar *>(BazPointer)->getValue(); + reinterpret_cast<const Foo *>(BazPointer)->getValue(); /* Test 5 */ // CHECK: reinterpret_cast<const Bar *>(BazPointer)->getValue(); + static_cast<const Foo &>(BazReference).getValue(); /* Test 6 */ // CHECK: static_cast<const Bar &>(BazReference).getValue(); + static_cast<const Foo *>(BazPointer)->getValue(); /* Test 7 */ // CHECK: static_cast<const Bar *>(BazPointer)->getValue(); + return 0; +} + +// Test 1. +// RUN: clang-rename -offset=30 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=155 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=1133 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// Test 4. +// RUN: clang-rename -offset=1266 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// Test 5. +// RUN: clang-rename -offset=1402 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// Test 6. +// RUN: clang-rename -offset=1533 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// Test 7. +// RUN: clang-rename -offset=1665 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/Ctor.cpp b/test/clang-rename/Ctor.cpp new file mode 100644 index 000000000000..9908a4123ddf --- /dev/null +++ b/test/clang-rename/Ctor.cpp @@ -0,0 +1,14 @@ +class Foo { // CHECK: class Bar { +public: + Foo(); /* Test 1 */ // CHECK: Bar(); +}; + +Foo::Foo() /* Test 2 */ {} // CHECK: Bar::Bar() /* Test 2 */ {} + +// Test 1. +// RUN: clang-rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/CtorInitializer.cpp b/test/clang-rename/CtorInitializer.cpp new file mode 100644 index 000000000000..fed4f5b06c27 --- /dev/null +++ b/test/clang-rename/CtorInitializer.cpp @@ -0,0 +1,17 @@ +class Baz {}; + +class Qux { + Baz Foo; /* Test 1 */ // CHECK: Baz Bar; +public: + Qux(); +}; + +Qux::Qux() : Foo() /* Test 2 */ {} // CHECK: Qux::Qux() : Bar() /* Test 2 */ {} + +// Test 1. +// RUN: clang-rename -offset=33 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=118 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/DeclRefExpr.cpp b/test/clang-rename/DeclRefExpr.cpp new file mode 100644 index 000000000000..6462862d82ad --- /dev/null +++ b/test/clang-rename/DeclRefExpr.cpp @@ -0,0 +1,24 @@ +class C { +public: + static int Foo; /* Test 1 */ // CHECK: static int Bar; +}; + +int foo(int x) { return 0; } +#define MACRO(a) foo(a) + +int main() { + C::Foo = 1; /* Test 2 */ // CHECK: C::Bar = 1; + MACRO(C::Foo); // CHECK: MACRO(C::Bar); + int y = C::Foo; /* Test 3 */ // CHECK: int y = C::Bar; + return 0; +} + +// Test 1. +// RUN: clang-rename -offset=31 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=152 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=271 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/Field.cpp b/test/clang-rename/Field.cpp new file mode 100644 index 000000000000..c0e9a019e47e --- /dev/null +++ b/test/clang-rename/Field.cpp @@ -0,0 +1,15 @@ +class Baz { + int Foo; /* Test 1 */ // CHECK: int Bar; +public: + Baz(); +}; + +Baz::Baz() : Foo(0) /* Test 2 */ {} // CHECK: Baz::Baz() : Bar(0) + +// Test 1. +// RUN: clang-rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=89 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/FunctionMacro.cpp b/test/clang-rename/FunctionMacro.cpp new file mode 100644 index 000000000000..6e87026ec706 --- /dev/null +++ b/test/clang-rename/FunctionMacro.cpp @@ -0,0 +1,20 @@ +#define moo foo // CHECK: #define moo macro_function + +int foo() /* Test 1 */ { // CHECK: int macro_function() /* Test 1 */ { + return 42; +} + +void boo(int value) {} + +void qoo() { + foo(); // CHECK: macro_function(); + boo(foo()); // CHECK: boo(macro_function()); + moo(); + boo(moo()); +} + +// Test 1. +// RUN: clang-rename -offset=68 -new-name=macro_function %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'foo.*' <file> diff --git a/test/clang-rename/FunctionOverride.cpp b/test/clang-rename/FunctionOverride.cpp new file mode 100644 index 000000000000..adfeb739e66d --- /dev/null +++ b/test/clang-rename/FunctionOverride.cpp @@ -0,0 +1,13 @@ +class A { virtual void foo(); /* Test 1 */ }; // CHECK: class A { virtual void bar(); +class B : public A { void foo(); /* Test 2 */ }; // CHECK: class B : public A { void bar(); +class C : public B { void foo(); /* Test 3 */ }; // CHECK: class C : public B { void bar(); + +// Test 1. +// RUN: clang-rename -offset=23 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=116 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=209 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'foo.*' <file> diff --git a/test/clang-rename/FunctionWithClassFindByName.cpp b/test/clang-rename/FunctionWithClassFindByName.cpp new file mode 100644 index 000000000000..2cae09a1c244 --- /dev/null +++ b/test/clang-rename/FunctionWithClassFindByName.cpp @@ -0,0 +1,12 @@ +void foo() { +} + +class Foo { // CHECK: class Bar +}; + +int main() { + Foo *Pointer = 0; // CHECK: Bar *Pointer = 0; + return 0; +} + +// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s diff --git a/test/clang-rename/IncludeHeaderWithSymbol.cpp b/test/clang-rename/IncludeHeaderWithSymbol.cpp new file mode 100644 index 000000000000..cb2baee57b89 --- /dev/null +++ b/test/clang-rename/IncludeHeaderWithSymbol.cpp @@ -0,0 +1,10 @@ +#include "Inputs/HeaderWithSymbol.h" + +int main() { + return 0; // CHECK: {{^ return 0;}} +} + +// Test 1. +// The file IncludeHeaderWithSymbol.cpp doesn't contain the symbol Foo +// and is expected to be written to stdout without modifications +// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | FileCheck %s diff --git a/test/clang-rename/Inputs/HeaderWithSymbol.h b/test/clang-rename/Inputs/HeaderWithSymbol.h new file mode 100644 index 000000000000..1fe02e89786c --- /dev/null +++ b/test/clang-rename/Inputs/HeaderWithSymbol.h @@ -0,0 +1 @@ +struct Foo {}; diff --git a/test/clang-rename/Inputs/OffsetToNewName.yaml b/test/clang-rename/Inputs/OffsetToNewName.yaml new file mode 100644 index 000000000000..d8e972880f36 --- /dev/null +++ b/test/clang-rename/Inputs/OffsetToNewName.yaml @@ -0,0 +1,6 @@ +--- +- Offset: 6 + NewName: Bar1 +- Offset: 44 + NewName: Bar2 +... diff --git a/test/clang-rename/Inputs/QualifiedNameToNewName.yaml b/test/clang-rename/Inputs/QualifiedNameToNewName.yaml new file mode 100644 index 000000000000..6e3783671dfa --- /dev/null +++ b/test/clang-rename/Inputs/QualifiedNameToNewName.yaml @@ -0,0 +1,6 @@ +--- +- QualifiedName: Foo1 + NewName: Bar1 +- QualifiedName: Foo2 + NewName: Bar2 +... diff --git a/test/clang-rename/InvalidNewName.cpp b/test/clang-rename/InvalidNewName.cpp new file mode 100644 index 000000000000..e6b38e59420a --- /dev/null +++ b/test/clang-rename/InvalidNewName.cpp @@ -0,0 +1,2 @@ +// RUN: not clang-rename -new-name=class -offset=133 %s 2>&1 | FileCheck %s +// CHECK: ERROR: new name is not a valid identifier in C++17. diff --git a/test/clang-rename/InvalidOffset.cpp b/test/clang-rename/InvalidOffset.cpp new file mode 100644 index 000000000000..2ae04d01e4a7 --- /dev/null +++ b/test/clang-rename/InvalidOffset.cpp @@ -0,0 +1,9 @@ +#include "Inputs/HeaderWithSymbol.h" +#define FOO int bar; +FOO + +int foo; + +// RUN: not clang-rename -new-name=qux -offset=259 %s -- 2>&1 | FileCheck %s +// CHECK-NOT: CHECK +// CHECK: error: SourceLocation in file {{.*}}InvalidOffset.cpp at offset 259 is invalid diff --git a/test/clang-rename/InvalidQualifiedName.cpp b/test/clang-rename/InvalidQualifiedName.cpp new file mode 100644 index 000000000000..5280e3939ccd --- /dev/null +++ b/test/clang-rename/InvalidQualifiedName.cpp @@ -0,0 +1,4 @@ +struct S { +}; + +// RUN: clang-rename -force -qualified-name S2 -new-name=T %s -- diff --git a/test/clang-rename/MemberExprMacro.cpp b/test/clang-rename/MemberExprMacro.cpp new file mode 100644 index 000000000000..56cd8d95f6e8 --- /dev/null +++ b/test/clang-rename/MemberExprMacro.cpp @@ -0,0 +1,22 @@ +class Baz { +public: + int Foo; /* Test 1 */ // CHECK: int Bar; +}; + +int qux(int x) { return 0; } +#define MACRO(a) qux(a) + +int main() { + Baz baz; + baz.Foo = 1; /* Test 2 */ // CHECK: baz.Bar = 1; + MACRO(baz.Foo); // CHECK: MACRO(baz.Bar); + int y = baz.Foo; // CHECK: int y = baz.Bar; +} + +// Test 1. +// RUN: clang-rename -offset=26 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=155 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/Namespace.cpp b/test/clang-rename/Namespace.cpp new file mode 100644 index 000000000000..ec9630fdedb6 --- /dev/null +++ b/test/clang-rename/Namespace.cpp @@ -0,0 +1,13 @@ +namespace gcc /* Test 1 */ { // CHECK: namespace clang /* Test 1 */ { + int x; +} + +void boo() { + gcc::x = 42; // CHECK: clang::x = 42; +} + +// Test 1. +// RUN: clang-rename -offset=10 -new-name=clang %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/NoNewName.cpp b/test/clang-rename/NoNewName.cpp new file mode 100644 index 000000000000..4f882d83b0c1 --- /dev/null +++ b/test/clang-rename/NoNewName.cpp @@ -0,0 +1,4 @@ +// Check for an error while -new-name argument has not been passed to +// clang-rename. +// RUN: not clang-rename -offset=133 %s 2>&1 | FileCheck %s +// CHECK: clang-rename: -new-name must be specified. diff --git a/test/clang-rename/TemplateClassInstantiation.cpp b/test/clang-rename/TemplateClassInstantiation.cpp new file mode 100644 index 000000000000..493d0951df57 --- /dev/null +++ b/test/clang-rename/TemplateClassInstantiation.cpp @@ -0,0 +1,42 @@ +template <typename T> +class Foo { /* Test 1 */ // CHECK: class Bar { /* Test 1 */ +public: + T foo(T arg, T& ref, T* ptr) { + T value; + int number = 42; + value = (T)number; + value = static_cast<T>(number); + return value; + } + static void foo(T value) {} + T member; +}; + +template <typename T> +void func() { + Foo<T> obj; /* Test 2 */ // CHECK: Bar<T> obj; + obj.member = T(); + Foo<T>::foo(); // CHECK: Bar<T>::foo(); +} + +int main() { + Foo<int> i; /* Test 3 */ // CHECK: Bar<int> i; + i.member = 0; + Foo<int>::foo(0); // CHECK: Bar<int>::foo(0); + + Foo<bool> b; // CHECK: Bar<bool> b; + b.member = false; + Foo<bool>::foo(false); // CHECK: Bar<bool>::foo(false); + + return 0; +} + +// Test 1. +// RUN: clang-rename -offset=29 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=324 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=463 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/TemplateTypename.cpp b/test/clang-rename/TemplateTypename.cpp new file mode 100644 index 000000000000..559ec1f9ade7 --- /dev/null +++ b/test/clang-rename/TemplateTypename.cpp @@ -0,0 +1,24 @@ +template <typename T /* Test 1 */> // CHECK: template <typename U /* Test 1 */> +class Foo { +T foo(T arg, T& ref, T* /* Test 2 */ ptr) { // CHECK: U foo(U arg, U& ref, U* /* Test 2 */ ptr) { + T value; // CHECK: U value; + int number = 42; + value = (T)number; // CHECK: value = (U)number; + value = static_cast<T /* Test 3 */>(number); // CHECK: value = static_cast<U /* Test 3 */>(number); + return value; +} + +static void foo(T value) {} // CHECK: static void foo(U value) {} + +T member; // CHECK: U member; +}; + +// Test 1. +// RUN: clang-rename -offset=19 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=126 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=392 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'T.*' <file> diff --git a/test/clang-rename/TemplatedClassFunction.cpp b/test/clang-rename/TemplatedClassFunction.cpp new file mode 100644 index 000000000000..1f5b0b52ba7a --- /dev/null +++ b/test/clang-rename/TemplatedClassFunction.cpp @@ -0,0 +1,22 @@ +template <typename T> +class A { +public: + void foo() /* Test 1 */ {} // CHECK: void bar() /* Test 1 */ {} +}; + +int main(int argc, char **argv) { + A<int> a; + a.foo(); /* Test 2 */ // CHECK: a.bar() /* Test 2 */ + return 0; +} + +// Test 1. +// RUN: clang-refactor rename -offset=48 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-refactor rename -offset=162 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// +// Currently unsupported test. +// XFAIL: * + +// To find offsets after modifying the file, use: +// grep -Ubo 'foo.*' <file> diff --git a/test/clang-rename/UserDefinedConversion.cpp b/test/clang-rename/UserDefinedConversion.cpp new file mode 100644 index 000000000000..60f251ab4483 --- /dev/null +++ b/test/clang-rename/UserDefinedConversion.cpp @@ -0,0 +1,26 @@ +class Foo { /* Test 1 */ // CHECK: class Bar { +public: + Foo() {} // CHECK: Bar() {} +}; + +class Baz { +public: + operator Foo() /* Test 2 */ const { // CHECK: operator Bar() /* Test 2 */ const { + Foo foo; // CHECK: Bar foo; + return foo; + } +}; + +int main() { + Baz boo; + Foo foo = static_cast<Foo>(boo); // CHECK: Bar foo = static_cast<Bar>(boo); + return 0; +} + +// Test 1. +// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=164 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/Variable.cpp b/test/clang-rename/Variable.cpp new file mode 100644 index 000000000000..d7e670fb43ee --- /dev/null +++ b/test/clang-rename/Variable.cpp @@ -0,0 +1,33 @@ +#define NAMESPACE namespace A +NAMESPACE { +int Foo; /* Test 1 */ // CHECK: int Bar; +} +int Foo; // CHECK: int Foo; +int Qux = Foo; // CHECK: int Qux = Foo; +int Baz = A::Foo; /* Test 2 */ // CHECK: Baz = A::Bar; +void fun() { + struct { + int Foo; // CHECK: int Foo; + } b = {100}; + int Foo = 100; // CHECK: int Foo = 100; + Baz = Foo; // CHECK: Baz = Foo; + { + extern int Foo; // CHECK: extern int Foo; + Baz = Foo; // CHECK: Baz = Foo; + Foo = A::Foo /* Test 3 */ + Baz; // CHECK: Foo = A::Bar /* Test 3 */ + Baz; + A::Foo /* Test 4 */ = b.Foo; // CHECK: A::Bar /* Test 4 */ = b.Foo; + } + Foo = b.Foo; // Foo = b.Foo; +} + +// Test 1. +// RUN: clang-rename -offset=46 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=234 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=641 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 4. +// RUN: clang-rename -offset=716 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/VariableMacro.cpp b/test/clang-rename/VariableMacro.cpp new file mode 100644 index 000000000000..622e825d3e41 --- /dev/null +++ b/test/clang-rename/VariableMacro.cpp @@ -0,0 +1,21 @@ +#define Baz Foo // CHECK: #define Baz Bar + +void foo(int value) {} + +void macro() { + int Foo; /* Test 1 */ // CHECK: int Bar; + Foo = 42; /* Test 2 */ // CHECK: Bar = 42; + Baz -= 0; + foo(Foo); /* Test 3 */ // CHECK: foo(Bar); + foo(Baz); +} + +// Test 1. +// RUN: clang-rename -offset=88 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -offset=129 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=191 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s + +// To find offsets after modifying the file, use: +// grep -Ubo 'Foo.*' <file> diff --git a/test/clang-rename/YAMLInput.cpp b/test/clang-rename/YAMLInput.cpp new file mode 100644 index 000000000000..55dbc6d66a5a --- /dev/null +++ b/test/clang-rename/YAMLInput.cpp @@ -0,0 +1,10 @@ +class Foo1 { // CHECK: class Bar1 +}; + +class Foo2 { // CHECK: class Bar2 +}; + +// Test 1. +// RUN: clang-rename -input %S/Inputs/OffsetToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-rename -input %S/Inputs/QualifiedNameToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b0c97f0f1e4c..4976332b7dbc 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -10,6 +10,8 @@ add_clang_subdirectory(clang-offload-bundler) add_clang_subdirectory(c-index-test) +add_clang_subdirectory(clang-rename) + if(CLANG_ENABLE_ARCMT) add_clang_subdirectory(arcmt-test) add_clang_subdirectory(c-arcmt-test) diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index d25ae117a68a..1e925569dd95 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -809,6 +809,37 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { if (clang_Cursor_isObjCOptional(Cursor)) printf(" (@optional)"); + switch (clang_getCursorExceptionSpecificationType(Cursor)) + { + case CXCursor_ExceptionSpecificationKind_None: + break; + + case CXCursor_ExceptionSpecificationKind_DynamicNone: + printf(" (noexcept dynamic none)"); + break; + + case CXCursor_ExceptionSpecificationKind_Dynamic: + printf(" (noexcept dynamic)"); + break; + + case CXCursor_ExceptionSpecificationKind_MSAny: + printf(" (noexcept dynamic any)"); + break; + + case CXCursor_ExceptionSpecificationKind_BasicNoexcept: + printf(" (noexcept)"); + break; + + case CXCursor_ExceptionSpecificationKind_ComputedNoexcept: + printf(" (computed-noexcept)"); + break; + + case CXCursor_ExceptionSpecificationKind_Unevaluated: + case CXCursor_ExceptionSpecificationKind_Uninstantiated: + case CXCursor_ExceptionSpecificationKind_Unparsed: + break; + } + { CXString language; CXString definedIn; diff --git a/tools/c-index-test/core_main.cpp b/tools/c-index-test/core_main.cpp index 4f2c3cb34a9b..c255f54ba68c 100644 --- a/tools/c-index-test/core_main.cpp +++ b/tools/c-index-test/core_main.cpp @@ -217,7 +217,7 @@ static bool printSourceSymbolsFromModule(StringRef modulePath, IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile( - modulePath, *pchRdr, Diags, + modulePath, *pchRdr, ASTUnit::LoadASTOnly, Diags, FileSystemOpts, /*UseDebugInfo=*/false, /*OnlyLocalDecls=*/true, None, /*CaptureDiagnostics=*/false, diff --git a/tools/clang-rename/CMakeLists.txt b/tools/clang-rename/CMakeLists.txt new file mode 100644 index 000000000000..771e3bdea6f0 --- /dev/null +++ b/tools/clang-rename/CMakeLists.txt @@ -0,0 +1,24 @@ +set(LLVM_LINK_COMPONENTS + Option + Support + ) + +add_clang_executable(clang-rename ClangRename.cpp) + +target_link_libraries(clang-rename + clangBasic + clangFrontend + clangRewrite + clangTooling + clangToolingCore + clangToolingRefactor + ) + +install(TARGETS clang-rename RUNTIME DESTINATION bin) + +install(PROGRAMS clang-rename.py + DESTINATION share/clang + COMPONENT clang-rename) +install(PROGRAMS clang-rename.el + DESTINATION share/clang + COMPONENT clang-rename) diff --git a/tools/clang-rename/ClangRename.cpp b/tools/clang-rename/ClangRename.cpp new file mode 100644 index 000000000000..cc18a05bcdbe --- /dev/null +++ b/tools/clang-rename/ClangRename.cpp @@ -0,0 +1,239 @@ +//===--- tools/extra/clang-rename/ClangRename.cpp - Clang rename tool -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements a clang-rename tool that automatically finds and +/// renames symbols in C++ code. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/Rename/RenamingAction.h" +#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h" +#include "clang/Tooling/ReplacementsYaml.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include <string> +#include <system_error> + +using namespace llvm; +using namespace clang; + +/// \brief An oldname -> newname rename. +struct RenameAllInfo { + unsigned Offset = 0; + std::string QualifiedName; + std::string NewName; +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(RenameAllInfo) + +namespace llvm { +namespace yaml { + +/// \brief Specialized MappingTraits to describe how a RenameAllInfo is +/// (de)serialized. +template <> struct MappingTraits<RenameAllInfo> { + static void mapping(IO &IO, RenameAllInfo &Info) { + IO.mapOptional("Offset", Info.Offset); + IO.mapOptional("QualifiedName", Info.QualifiedName); + IO.mapRequired("NewName", Info.NewName); + } +}; + +} // end namespace yaml +} // end namespace llvm + +static cl::OptionCategory ClangRenameOptions("clang-rename common options"); + +static cl::list<unsigned> SymbolOffsets( + "offset", + cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), + cl::ZeroOrMore, cl::cat(ClangRenameOptions)); +static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."), + cl::cat(ClangRenameOptions)); +static cl::list<std::string> + QualifiedNames("qualified-name", + cl::desc("The fully qualified name of the symbol."), + cl::ZeroOrMore, cl::cat(ClangRenameOptions)); + +static cl::list<std::string> + NewNames("new-name", cl::desc("The new name to change the symbol to."), + cl::ZeroOrMore, cl::cat(ClangRenameOptions)); +static cl::opt<bool> PrintName( + "pn", + cl::desc("Print the found symbol's name prior to renaming to stderr."), + cl::cat(ClangRenameOptions)); +static cl::opt<bool> PrintLocations( + "pl", cl::desc("Print the locations affected by renaming to stderr."), + cl::cat(ClangRenameOptions)); +static cl::opt<std::string> + ExportFixes("export-fixes", + cl::desc("YAML file to store suggested fixes in."), + cl::value_desc("filename"), cl::cat(ClangRenameOptions)); +static cl::opt<std::string> + Input("input", cl::desc("YAML file to load oldname-newname pairs from."), + cl::Optional, cl::cat(ClangRenameOptions)); +static cl::opt<bool> Force("force", + cl::desc("Ignore nonexistent qualified names."), + cl::cat(ClangRenameOptions)); + +int main(int argc, const char **argv) { + tooling::CommonOptionsParser OP(argc, argv, ClangRenameOptions); + + if (!Input.empty()) { + // Populate QualifiedNames and NewNames from a YAML file. + ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = + llvm::MemoryBuffer::getFile(Input); + if (!Buffer) { + errs() << "clang-rename: failed to read " << Input << ": " + << Buffer.getError().message() << "\n"; + return 1; + } + + std::vector<RenameAllInfo> Infos; + llvm::yaml::Input YAML(Buffer.get()->getBuffer()); + YAML >> Infos; + for (const auto &Info : Infos) { + if (!Info.QualifiedName.empty()) + QualifiedNames.push_back(Info.QualifiedName); + else + SymbolOffsets.push_back(Info.Offset); + NewNames.push_back(Info.NewName); + } + } + + // Check the arguments for correctness. + if (NewNames.empty()) { + errs() << "clang-rename: -new-name must be specified.\n\n"; + return 1; + } + + if (SymbolOffsets.empty() == QualifiedNames.empty()) { + errs() << "clang-rename: -offset and -qualified-name can't be present at " + "the same time.\n"; + return 1; + } + + // Check if NewNames is a valid identifier in C++17. + LangOptions Options; + Options.CPlusPlus = true; + Options.CPlusPlus1z = true; + IdentifierTable Table(Options); + for (const auto &NewName : NewNames) { + auto NewNameTokKind = Table.get(NewName).getTokenID(); + if (!tok::isAnyIdentifier(NewNameTokKind)) { + errs() << "ERROR: new name is not a valid identifier in C++17.\n\n"; + return 1; + } + } + + if (SymbolOffsets.size() + QualifiedNames.size() != NewNames.size()) { + errs() << "clang-rename: number of symbol offsets(" << SymbolOffsets.size() + << ") + number of qualified names (" << QualifiedNames.size() + << ") must be equal to number of new names(" << NewNames.size() + << ").\n\n"; + cl::PrintHelpMessage(); + return 1; + } + + auto Files = OP.getSourcePathList(); + tooling::RefactoringTool Tool(OP.getCompilations(), Files); + tooling::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force); + Tool.run(tooling::newFrontendActionFactory(&FindingAction).get()); + const std::vector<std::vector<std::string>> &USRList = + FindingAction.getUSRList(); + const std::vector<std::string> &PrevNames = FindingAction.getUSRSpellings(); + if (PrintName) { + for (const auto &PrevName : PrevNames) { + outs() << "clang-rename found name: " << PrevName << '\n'; + } + } + + if (FindingAction.errorOccurred()) { + // Diagnostics are already issued at this point. + return 1; + } + + if (Force && PrevNames.size() < NewNames.size()) { + // No matching PrevName for all NewNames. Without Force this is an error + // above already. + return 0; + } + + // Perform the renaming. + tooling::RenamingAction RenameAction(NewNames, PrevNames, USRList, + Tool.getReplacements(), PrintLocations); + std::unique_ptr<tooling::FrontendActionFactory> Factory = + tooling::newFrontendActionFactory(&RenameAction); + int ExitCode; + + if (Inplace) { + ExitCode = Tool.runAndSave(Factory.get()); + } else { + ExitCode = Tool.run(Factory.get()); + + if (!ExportFixes.empty()) { + std::error_code EC; + llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None); + if (EC) { + llvm::errs() << "Error opening output file: " << EC.message() << '\n'; + return 1; + } + + // Export replacements. + tooling::TranslationUnitReplacements TUR; + const auto &FileToReplacements = Tool.getReplacements(); + for (const auto &Entry : FileToReplacements) + TUR.Replacements.insert(TUR.Replacements.end(), Entry.second.begin(), + Entry.second.end()); + + yaml::Output YAML(OS); + YAML << TUR; + OS.close(); + return 0; + } + + // Write every file to stdout. Right now we just barf the files without any + // indication of which files start where, other than that we print the files + // in the same order we see them. + LangOptions DefaultLangOptions; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); + TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); + DiagnosticsEngine Diagnostics( + IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, + &DiagnosticPrinter, false); + auto &FileMgr = Tool.getFiles(); + SourceManager Sources(Diagnostics, FileMgr); + Rewriter Rewrite(Sources, DefaultLangOptions); + + Tool.applyAllReplacements(Rewrite); + for (const auto &File : Files) { + const auto *Entry = FileMgr.getFile(File); + const auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User); + Rewrite.getEditBuffer(ID).write(outs()); + } + } + + return ExitCode; +} diff --git a/tools/clang-rename/clang-rename.el b/tools/clang-rename/clang-rename.el new file mode 100644 index 000000000000..b6c3ed4c686b --- /dev/null +++ b/tools/clang-rename/clang-rename.el @@ -0,0 +1,79 @@ +;;; clang-rename.el --- Renames every occurrence of a symbol found at <offset>. -*- lexical-binding: t; -*- + +;; Keywords: tools, c + +;;; Commentary: + +;; To install clang-rename.el make sure the directory of this file is in your +;; `load-path' and add +;; +;; (require 'clang-rename) +;; +;; to your .emacs configuration. + +;;; Code: + +(defgroup clang-rename nil + "Integration with clang-rename" + :group 'c) + +(defcustom clang-rename-binary "clang-rename" + "Path to clang-rename executable." + :type '(file :must-match t) + :group 'clang-rename) + +;;;###autoload +(defun clang-rename (new-name) + "Rename all instances of the symbol at point to NEW-NAME using clang-rename." + (interactive "sEnter a new name: ") + (save-some-buffers :all) + ;; clang-rename should not be combined with other operations when undoing. + (undo-boundary) + (let ((output-buffer (get-buffer-create "*clang-rename*"))) + (with-current-buffer output-buffer (erase-buffer)) + (let ((exit-code (call-process + clang-rename-binary nil output-buffer nil + (format "-offset=%d" + ;; clang-rename wants file (byte) offsets, not + ;; buffer (character) positions. + (clang-rename--bufferpos-to-filepos + ;; Emacs treats one character after a symbol as + ;; part of the symbol, but clang-rename doesn’t. + ;; Use the beginning of the current symbol, if + ;; available, to resolve the inconsistency. + (or (car (bounds-of-thing-at-point 'symbol)) + (point)) + 'exact)) + (format "-new-name=%s" new-name) + "-i" (buffer-file-name)))) + (if (and (integerp exit-code) (zerop exit-code)) + ;; Success; revert current buffer so it gets the modifications. + (progn + (kill-buffer output-buffer) + (revert-buffer :ignore-auto :noconfirm :preserve-modes)) + ;; Failure; append exit code to output buffer and display it. + (let ((message (clang-rename--format-message + "clang-rename failed with %s %s" + (if (integerp exit-code) "exit status" "signal") + exit-code))) + (with-current-buffer output-buffer + (insert ?\n message ?\n)) + (message "%s" message) + (display-buffer output-buffer)))))) + +(defalias 'clang-rename--bufferpos-to-filepos + (if (fboundp 'bufferpos-to-filepos) + 'bufferpos-to-filepos + ;; Emacs 24 doesn’t have ‘bufferpos-to-filepos’, simulate it using + ;; ‘position-bytes’. + (lambda (position &optional _quality _coding-system) + (1- (position-bytes position))))) + +;; ‘format-message’ is new in Emacs 25.1. Provide a fallback for older +;; versions. +(defalias 'clang-rename--format-message + (if (fboundp 'format-message) 'format-message 'format)) + +(provide 'clang-rename) + +;;; clang-rename.el ends here diff --git a/tools/clang-rename/clang-rename.py b/tools/clang-rename/clang-rename.py new file mode 100644 index 000000000000..3cc6644ff8f0 --- /dev/null +++ b/tools/clang-rename/clang-rename.py @@ -0,0 +1,61 @@ +''' +Minimal clang-rename integration with Vim. + +Before installing make sure one of the following is satisfied: + +* clang-rename is in your PATH +* `g:clang_rename_path` in ~/.vimrc points to valid clang-rename executable +* `binary` in clang-rename.py points to valid to clang-rename executable + +To install, simply put this into your ~/.vimrc + + noremap <leader>cr :pyf <path-to>/clang-rename.py<cr> + +IMPORTANT NOTE: Before running the tool, make sure you saved the file. + +All you have to do now is to place a cursor on a variable/function/class which +you would like to rename and press '<leader>cr'. You will be prompted for a new +name if the cursor points to a valid symbol. +''' + +import vim +import subprocess +import sys + +def main(): + binary = 'clang-rename' + if vim.eval('exists("g:clang_rename_path")') == "1": + binary = vim.eval('g:clang_rename_path') + + # Get arguments for clang-rename binary. + offset = int(vim.eval('line2byte(line("."))+col(".")')) - 2 + if offset < 0: + print >> sys.stderr, '''Couldn\'t determine cursor position. + Is your file empty?''' + return + filename = vim.current.buffer.name + + new_name_request_message = 'type new name:' + new_name = vim.eval("input('{}\n')".format(new_name_request_message)) + + # Call clang-rename. + command = [binary, + filename, + '-i', + '-offset', str(offset), + '-new-name', str(new_name)] + # FIXME: make it possible to run the tool on unsaved file. + p = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + + if stderr: + print stderr + + # Reload all buffers in Vim. + vim.command("checktime") + + +if __name__ == '__main__': + main() diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index af25d9598021..9f37c428ff93 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -462,7 +462,7 @@ int main(int argc_, const char **argv_) { std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv)); int Res = 1; - if (C.get()) { + if (C && !C->containsError()) { SmallVector<std::pair<int, const Command *>, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f92096195081..deaab3608e62 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3247,7 +3247,8 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx, IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile( - ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(), Diags, + ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(), + ASTUnit::LoadEverything, Diags, FileSystemOpts, /*UseDebugInfo=*/false, CXXIdx->getOnlyLocalDecls(), None, /*CaptureDiagnostics=*/true, diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp index de223d3043a3..4e47b25a4bf0 100644 --- a/tools/libclang/CIndexDiagnostic.cpp +++ b/tools/libclang/CIndexDiagnostic.cpp @@ -110,40 +110,34 @@ public: CurrentSet = &CD.getChildDiagnostics(); } - void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, + void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, - const SourceManager *SM, DiagOrStoredDiag D) override { if (!D.isNull()) return; CXSourceLocation L; - if (SM) - L = translateSourceLocation(*SM, LangOpts, Loc); + if (Loc.hasManager()) + L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); else L = clang_getNullLocation(); CurrentSet->appendDiagnostic( llvm::make_unique<CXDiagnosticCustomNoteImpl>(Message, L)); } - void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges, - const SourceManager &SM) override {} + ArrayRef<CharSourceRange> Ranges) override {} - void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) override {} + void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints) override {} - void emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) override { + void emitNote(FullSourceLoc Loc, StringRef Message) override { CXSourceLocation L; - if (SM) - L = translateSourceLocation(*SM, LangOpts, Loc); + if (Loc.hasManager()) + L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); else L = clang_getNullLocation(); CurrentSet->appendDiagnostic( diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index df9aa656b5d9..5875459734a2 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -684,6 +684,24 @@ CXType clang_getCursorResultType(CXCursor C) { return MakeCXType(QualType(), cxcursor::getCursorTU(C)); } +int clang_getExceptionSpecificationType(CXType X) { + QualType T = GetQualType(X); + if (T.isNull()) + return -1; + + if (const auto *FD = T->getAs<FunctionProtoType>()) + return static_cast<int>(FD->getExceptionSpecType()); + + return -1; +} + +int clang_getCursorExceptionSpecificationType(CXCursor C) { + if (clang_isDeclaration(C.kind)) + return clang_getExceptionSpecificationType(clang_getCursorType(C)); + + return -1; +} + unsigned clang_isPODType(CXType X) { QualType T = GetQualType(X); if (T.isNull()) diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 187d4749ebc1..e78899e4c759 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -175,6 +175,7 @@ clang_getCursorCompletionString clang_getCursorDefinition clang_getCursorDisplayName clang_getCursorExtent +clang_getCursorExceptionSpecificationType clang_getCursorKind clang_getCursorKindSpelling clang_getCursorLanguage @@ -210,6 +211,7 @@ clang_getElementType clang_getEnumConstantDeclUnsignedValue clang_getEnumConstantDeclValue clang_getEnumDeclIntegerType +clang_getExceptionSpecificationType clang_getFieldDeclBitWidth clang_getExpansionLocation clang_getFile diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 7d407ce3f649..b622d66af4ed 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -29,3 +29,4 @@ add_subdirectory(CodeGen) if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD) add_subdirectory(libclang) endif() +add_subdirectory(Rename) diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp index bce2748aa21b..ec50560b202b 100644 --- a/unittests/Driver/ToolChainTest.cpp +++ b/unittests/Driver/ToolChainTest.cpp @@ -152,5 +152,16 @@ TEST(ToolChainTest, DefaultDriverMode) { EXPECT_TRUE(CXXDriver.CCCIsCXX()); EXPECT_TRUE(CLDriver.IsCLMode()); } +TEST(ToolChainTest, InvalidArgument) { + IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); + struct TestDiagnosticConsumer : public DiagnosticConsumer {}; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags); + std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( + {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"})); + EXPECT_TRUE(C); + EXPECT_TRUE(C->containsError()); +} } // end anonymous namespace. diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 64bb28e0be23..b5f959f9c1f7 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -6004,7 +6004,10 @@ TEST_F(FormatTest, LayoutBraceInitializersInReturnStatement) { TEST_F(FormatTest, LayoutCxx11BraceInitializers) { verifyFormat("vector<int> x{1, 2, 3, 4};"); verifyFormat("vector<int> x{\n" - " 1, 2, 3, 4,\n" + " 1,\n" + " 2,\n" + " 3,\n" + " 4,\n" "};"); verifyFormat("vector<T> x{{}, {}, {}, {}};"); verifyFormat("f({1, 2});"); @@ -6049,6 +6052,17 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { "};"); verifyFormat("#define A {a, a},"); + // Binpacking only if there is no trailing comma + verifyFormat("const Aaaaaa aaaaa = {aaaaaaaaaa, bbbbbbbbbb,\n" + " cccccccccc, dddddddddd};", + getLLVMStyleWithColumns(50)); + verifyFormat("const Aaaaaa aaaaa = {\n" + " aaaaaaaaaaa,\n" + " bbbbbbbbbbb,\n" + " ccccccccccc,\n" + " ddddddddddd,\n" + "};", getLLVMStyleWithColumns(50)); + // Cases where distinguising braced lists and blocks is hard. verifyFormat("vector<int> v{12} GUARDED_BY(mutex);"); verifyFormat("void f() {\n" @@ -6128,10 +6142,12 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { " // Second element:\n" " 2};", getLLVMStyleWithColumns(30))); - // A trailing comma should still lead to an enforced line break. + // A trailing comma should still lead to an enforced line break and no + // binpacking. EXPECT_EQ("vector<int> SomeVector = {\n" " // aaa\n" - " 1, 2,\n" + " 1,\n" + " 2,\n" "};", format("vector<int> SomeVector = { // aaa\n" " 1, 2, };")); @@ -6297,7 +6313,7 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { " aaaaaaaaaaaa, a, aaaaaaaaaa, aaaaaaaaa, aaa}};"); // No column layout should be used here. - verifyFormat("aaaaaaaaaaaaaaa = {aaaaaaaaaaaaaaaaaaaaaaaaaaa, 0, 0,\n" + verifyFormat("aaaaaaaaaaaaaaa = {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0, 0,\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb};"); verifyNoCrash("a<,"); @@ -6555,12 +6571,12 @@ TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) { MergeInlineOnly); } -TEST_F(FormatTest, SplitEmptyFunctionBody) { +TEST_F(FormatTest, SplitEmptyFunction) { FormatStyle Style = getLLVMStyle(); Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterFunction = true; - Style.BraceWrapping.SplitEmptyFunctionBody = false; + Style.BraceWrapping.SplitEmptyFunction = false; Style.ColumnLimit = 40; verifyFormat("int f()\n" @@ -6623,6 +6639,178 @@ TEST_F(FormatTest, SplitEmptyFunctionBody) { Style); } +TEST_F(FormatTest, SplitEmptyClass) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterClass = true; + Style.BraceWrapping.SplitEmptyRecord = false; + + verifyFormat("class Foo\n" + "{};", + Style); + verifyFormat("/* something */ class Foo\n" + "{};", + Style); + verifyFormat("template <typename X> class Foo\n" + "{};", + Style); + verifyFormat("class Foo\n" + "{\n" + " Foo();\n" + "};", + Style); + verifyFormat("typedef class Foo\n" + "{\n" + "} Foo_t;", + Style); +} + +TEST_F(FormatTest, SplitEmptyStruct) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterStruct = true; + Style.BraceWrapping.SplitEmptyRecord = false; + + verifyFormat("struct Foo\n" + "{};", + Style); + verifyFormat("/* something */ struct Foo\n" + "{};", + Style); + verifyFormat("template <typename X> struct Foo\n" + "{};", + Style); + verifyFormat("struct Foo\n" + "{\n" + " Foo();\n" + "};", + Style); + verifyFormat("typedef struct Foo\n" + "{\n" + "} Foo_t;", + Style); + //typedef struct Bar {} Bar_t; +} + +TEST_F(FormatTest, SplitEmptyUnion) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterUnion = true; + Style.BraceWrapping.SplitEmptyRecord = false; + + verifyFormat("union Foo\n" + "{};", + Style); + verifyFormat("/* something */ union Foo\n" + "{};", + Style); + verifyFormat("union Foo\n" + "{\n" + " A,\n" + "};", + Style); + verifyFormat("typedef union Foo\n" + "{\n" + "} Foo_t;", + Style); +} + +TEST_F(FormatTest, SplitEmptyNamespace) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterNamespace = true; + Style.BraceWrapping.SplitEmptyNamespace = false; + + verifyFormat("namespace Foo\n" + "{};", + Style); + verifyFormat("/* something */ namespace Foo\n" + "{};", + Style); + verifyFormat("inline namespace Foo\n" + "{};", + Style); + verifyFormat("namespace Foo\n" + "{\n" + "void Bar();\n" + "};", + Style); +} + +TEST_F(FormatTest, NeverMergeShortRecords) { + FormatStyle Style = getLLVMStyle(); + + verifyFormat("class Foo {\n" + " Foo();\n" + "};", + Style); + verifyFormat("typedef class Foo {\n" + " Foo();\n" + "} Foo_t;", + Style); + verifyFormat("struct Foo {\n" + " Foo();\n" + "};", + Style); + verifyFormat("typedef struct Foo {\n" + " Foo();\n" + "} Foo_t;", + Style); + verifyFormat("union Foo {\n" + " A,\n" + "};", + Style); + verifyFormat("typedef union Foo {\n" + " A,\n" + "} Foo_t;", + Style); + verifyFormat("namespace Foo {\n" + "void Bar();\n" + "};", + Style); + + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterClass = true; + Style.BraceWrapping.AfterStruct = true; + Style.BraceWrapping.AfterUnion = true; + Style.BraceWrapping.AfterNamespace = true; + verifyFormat("class Foo\n" + "{\n" + " Foo();\n" + "};", + Style); + verifyFormat("typedef class Foo\n" + "{\n" + " Foo();\n" + "} Foo_t;", + Style); + verifyFormat("struct Foo\n" + "{\n" + " Foo();\n" + "};", + Style); + verifyFormat("typedef struct Foo\n" + "{\n" + " Foo();\n" + "} Foo_t;", + Style); + verifyFormat("union Foo\n" + "{\n" + " A,\n" + "};", + Style); + verifyFormat("typedef union Foo\n" + "{\n" + " A,\n" + "} Foo_t;", + Style); + verifyFormat("namespace Foo\n" + "{\n" + "void Bar();\n" + "};", + Style); +} + TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) { // Elaborate type variable declarations. verifyFormat("struct foo a = {bar};\nint n;"); @@ -9355,7 +9543,9 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch); CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse); CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces); - CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunctionBody); + CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction); + CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord); + CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyNamespace); } #undef CHECK_PARSE_BOOL diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp index 6e685f6703e1..b9cfaffb0181 100644 --- a/unittests/Format/FormatTestJava.cpp +++ b/unittests/Format/FormatTestJava.cpp @@ -237,7 +237,10 @@ TEST_F(FormatTestJava, EnumDeclarations) { TEST_F(FormatTestJava, ArrayInitializers) { verifyFormat("new int[] {1, 2, 3, 4};"); verifyFormat("new int[] {\n" - " 1, 2, 3, 4,\n" + " 1,\n" + " 2,\n" + " 3,\n" + " 4,\n" "};"); FormatStyle Style = getStyleWithColumns(65); diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp index d174c65a1f32..2e3b9311d12c 100644 --- a/unittests/Format/FormatTestProto.cpp +++ b/unittests/Format/FormatTestProto.cpp @@ -61,6 +61,29 @@ TEST_F(FormatTestProto, FormatsMessages) { " really.really.long.qualified.type.aaa.aaaaaaa.aaaaaaaa\n" " another_fiiiiiiiiiiiiiiiiiiiiield = 2;\n" "}"); + verifyFormat("message SomeMessage {\n" + " map<string, Project> projects = 1;\n" + " optional map<string, int32> size_projects = 2;\n" + " map<int, really.really.really.long.qualified.type.nameeee>\n" + " projects = 3;\n" + " map<int, really.really.really.really.long.qualified.type\n" + " .nameeee> projects = 4;\n" + " map<int,\n" + " reallyreallyreallyreallyreallyreallyreallylongname>\n" + " projects = 5;\n" + " map<int, Project>\n" + " longlonglonglonglonglonglonglonglonglongonglon = 6;\n" + " map<releleallyreallyreallyreallyreallyreallyreallylongname,\n" + " int> projects = 7;\n" + " map<releleallyreallyreallyreallyreallyreallyreallylongname,\n" + " releleallyreallyreallyreallyreallyreallyreallylongname>\n" + " releleallyreallyreallyreallyreallyreallyreallylongnam =\n" + " 8;\n" + " map<relele.llyreal.yreallyr.allyreally.eallyreal\n" + " .sauenirylongname,\n" + " really.really.really.really.long.qualified.type\n" + " .nameeee> projects = 9;\n" + "}"); } TEST_F(FormatTestProto, KeywordsInOtherLanguages) { @@ -178,12 +201,161 @@ TEST_F(FormatTestProto, FormatsOptions) { " field_c: \"OK\"\n" " msg_field{field_d: 123}\n" "};"); + verifyFormat("option (MyProto.options) = {\n" + " field_a: OK\n" + " field_b{field_c: OK}\n" + " field_d: OKOKOK\n" + " field_e: OK\n" + "}"); // Support syntax with <> instead of {}. verifyFormat("option (MyProto.options) = {\n" " field_c: \"OK\",\n" " msg_field: <field_d: 123>\n" "};"); + + verifyFormat("option (MyProto.options) = {\n" + " field_a: OK\n" + " field_b<field_c: OK>\n" + " field_d: OKOKOK\n" + " field_e: OK\n" + "}"); + + verifyFormat("option (MyProto.options) = {\n" + " msg_field: <>\n" + " field_c: \"OK\",\n" + " msg_field: <field_d: 123>\n" + " field_e: OK\n" + " msg_field: <field_d: 12>\n" + "};"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: OK\n" + " field_b: \"OK\"\n" + " field_c: 1\n" + " field_d: 12.5\n" + " field_e: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: OK,\n" + " field_b: \"OK\",\n" + " field_c: 1,\n" + " field_d: 12.5,\n" + " field_e: OK,\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field: {field_b: OK}\n" + " field_g: OK\n" + " field_g: OK\n" + " field_g: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field<\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " field_e: OK\n" + " field_f: OK\n" + " >\n" + " field_g: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field<\n" + " field_b: OK,\n" + " field_c: OK,\n" + " field_d: OK,\n" + " field_e: OK,\n" + " field_f: OK\n" + " >\n" + " field_g: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field: <\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " field_e: OK\n" + " field_f: OK\n" + " >\n" + " field_g: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field: {\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " field_e: OK\n" + " field_f: OK\n" + " }\n" + " field_g: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field{\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " field_e: OK\n" + " field_f: OK\n" + " }\n" + " field_g: OK\n" + ">;"); + + verifyFormat("option (MyProto.options) = {\n" + " field_a: \"OK\"\n" + " msg_field<\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " field_e: OK\n" + " field_f: OK\n" + " >\n" + " field_g: OK\n" + "};"); + + verifyFormat("option (MyProto.options) = {\n" + " field_a: \"OK\"\n" + " msg_field: <\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " field_e: OK\n" + " field_f: OK\n" + " >\n" + " field_g: OK\n" + "};"); + + verifyFormat("option (MyProto.options) = <\n" + " field_a: \"OK\"\n" + " msg_field{\n" + " field_b: OK\n" + " field_c: OK\n" + " field_d: OK\n" + " msg_field<\n" + " field_A: 1\n" + " field_B: 2\n" + " field_C: 3\n" + " field_D: 4\n" + " field_E: 5\n" + " >\n" + " msg_field<field_A: 1 field_B: 2 field_C: 3 field_D: 4>\n" + " field_e: OK\n" + " field_f: OK\n" + " }\n" + " field_g: OK\n" + ">;"); } TEST_F(FormatTestProto, FormatsService) { diff --git a/unittests/Format/SortIncludesTest.cpp b/unittests/Format/SortIncludesTest.cpp index c3c56a813041..1128ed829ff2 100644 --- a/unittests/Format/SortIncludesTest.cpp +++ b/unittests/Format/SortIncludesTest.cpp @@ -266,6 +266,29 @@ TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { "a.cc")); } +TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { + // Setup an regex for main includes so we can cover those as well. + Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; + + // Ensure both main header detection and grouping work in a case insensitive + // manner. + EXPECT_EQ("#include \"llvm/A.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"LLVM/z.h\"\n" + "#include \"llvm/X.h\"\n" + "#include \"GTest/GTest.h\"\n" + "#include \"gmock/gmock.h\"\n", + sort("#include \"c.h\"\n" + "#include \"b.h\"\n" + "#include \"GTest/GTest.h\"\n" + "#include \"llvm/A.h\"\n" + "#include \"gmock/gmock.h\"\n" + "#include \"llvm/X.h\"\n" + "#include \"LLVM/z.h\"\n", + "a_TEST.cc")); +} + TEST_F(SortIncludesTest, NegativePriorities) { Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}}; EXPECT_EQ("#include \"important_os_header.h\"\n" diff --git a/unittests/Rename/CMakeLists.txt b/unittests/Rename/CMakeLists.txt new file mode 100644 index 000000000000..aa7609260cc0 --- /dev/null +++ b/unittests/Rename/CMakeLists.txt @@ -0,0 +1,22 @@ +set(LLVM_LINK_COMPONENTS + support + ) + +# We'd like clang/unittests/Tooling/RewriterTestContext.h in the test. +include_directories(${CLANG_SOURCE_DIR}) + +add_clang_unittest(ClangRenameTests + RenameClassTest.cpp + ) + +target_link_libraries(ClangRenameTests + clangAST + clangASTMatchers + clangBasic + clangFormat + clangFrontend + clangRewrite + clangTooling + clangToolingCore + clangToolingRefactor + ) diff --git a/unittests/Rename/ClangRenameTest.h b/unittests/Rename/ClangRenameTest.h new file mode 100644 index 000000000000..0933dd5aaf4f --- /dev/null +++ b/unittests/Rename/ClangRenameTest.h @@ -0,0 +1,112 @@ +//===-- ClangRenameTests.cpp - clang-rename unit tests --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "unittests/Tooling/RewriterTestContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Format/Format.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/Rename/RenamingAction.h" +#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MemoryBuffer.h" +#include "gtest/gtest.h" +#include <memory> +#include <string> +#include <vector> + +namespace clang { +namespace clang_rename { +namespace test { + +struct Case { + std::string Before; + std::string After; + std::string OldName; + std::string NewName; +}; + +class ClangRenameTest : public testing::Test, + public testing::WithParamInterface<Case> { +protected: + void AppendToHeader(StringRef Code) { HeaderContent += Code.str(); } + + std::string runClangRenameOnCode(llvm::StringRef Code, + llvm::StringRef OldName, + llvm::StringRef NewName) { + std::string NewCode; + llvm::raw_string_ostream(NewCode) << llvm::format( + "#include \"%s\"\n%s", HeaderName.c_str(), Code.str().c_str()); + tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent}, + {CCName, NewCode}}; + clang::RewriterTestContext Context; + Context.createInMemoryFile(HeaderName, HeaderContent); + clang::FileID InputFileID = Context.createInMemoryFile(CCName, NewCode); + + tooling::USRFindingAction FindingAction({}, {OldName}, false); + std::unique_ptr<tooling::FrontendActionFactory> USRFindingActionFactory = + tooling::newFrontendActionFactory(&FindingAction); + + if (!tooling::runToolOnCodeWithArgs( + USRFindingActionFactory->create(), NewCode, {"-std=c++11"}, CCName, + "clang-rename", std::make_shared<PCHContainerOperations>(), + FileContents)) + return ""; + + const std::vector<std::vector<std::string>> &USRList = + FindingAction.getUSRList(); + std::vector<std::string> NewNames = {NewName}; + std::map<std::string, tooling::Replacements> FileToReplacements; + tooling::QualifiedRenamingAction RenameAction(NewNames, USRList, + FileToReplacements); + auto RenameActionFactory = tooling::newFrontendActionFactory(&RenameAction); + if (!tooling::runToolOnCodeWithArgs( + RenameActionFactory->create(), NewCode, {"-std=c++11"}, CCName, + "clang-rename", std::make_shared<PCHContainerOperations>(), + FileContents)) + return ""; + + formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm"); + return Context.getRewrittenText(InputFileID); + } + + void CompareSnippets(StringRef Expected, StringRef Actual) { + std::string ExpectedCode; + llvm::raw_string_ostream(ExpectedCode) << llvm::format( + "#include \"%s\"\n%s", HeaderName.c_str(), Expected.str().c_str()); + EXPECT_EQ(format(ExpectedCode), format(Actual)); + } + + std::string format(llvm::StringRef Code) { + tooling::Replacements Replaces = format::reformat( + format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())}); + auto ChangedCode = tooling::applyAllReplacements(Code, Replaces); + EXPECT_TRUE(static_cast<bool>(ChangedCode)); + if (!ChangedCode) { + llvm::errs() << llvm::toString(ChangedCode.takeError()); + return ""; + } + return *ChangedCode; + } + + std::string HeaderContent; + std::string HeaderName = "header.h"; + std::string CCName = "input.cc"; +}; + +} // namespace test +} // namespace clang_rename +} // namesdpace clang diff --git a/unittests/Rename/RenameClassTest.cpp b/unittests/Rename/RenameClassTest.cpp new file mode 100644 index 000000000000..29b4594fb0a4 --- /dev/null +++ b/unittests/Rename/RenameClassTest.cpp @@ -0,0 +1,684 @@ +//===-- RenameClassTest.cpp - unit tests for renaming classes -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangRenameTest.h" + +namespace clang { +namespace clang_rename { +namespace test { +namespace { + +class RenameClassTest : public ClangRenameTest { +public: + RenameClassTest() { + AppendToHeader(R"( + namespace a { + class Foo { + public: + struct Nested { + enum NestedEnum {E1, E2}; + }; + void func() {} + static int Constant; + }; + class Goo { + public: + struct Nested { + enum NestedEnum {E1, E2}; + }; + }; + int Foo::Constant = 1; + } // namespace a + namespace b { + class Foo {}; + } // namespace b + + #define MACRO(x) x + + template<typename T> class ptr {}; + )"); + } +}; + +INSTANTIATE_TEST_CASE_P( + RenameClassTests, RenameClassTest, + testing::ValuesIn(std::vector<Case>({ + // basic classes + {"a::Foo f;", "b::Bar f;", "", ""}, + {"void f(a::Foo f) {}", "void f(b::Bar f) {}", "", ""}, + {"void f(a::Foo *f) {}", "void f(b::Bar *f) {}", "", ""}, + {"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }", + "", ""}, + {"namespace a {a::Foo f() { return Foo(); }}", + "namespace a {b::Bar f() { return b::Bar(); }}", "", ""}, + {"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}", "", ""}, + {"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}", "", ""}, + {"namespace a { void f(Foo a1) {} }", + "namespace a { void f(b::Bar a1) {} }", "", ""}, + {"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}", "", ""}, + {"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}", "", ""}, + {"a::Foo::Nested ns;", "b::Bar::Nested ns;", "", ""}, + {"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;", "", ""}, + {"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested", + "a::Foo::Nested2"}, + + // use namespace and typedefs + {"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;", "", ""}, + {"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}", + "", ""}, + {"using a::Foo; namespace x { Foo gA; }", + "using b::Bar; namespace x { Bar gA; }", "", ""}, + {"struct S { using T = a::Foo; T a_; };", + "struct S { using T = b::Bar; T a_; };", "", ""}, + {"using T = a::Foo; T gA;", "using T = b::Bar; T gA;", "", ""}, + {"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;", "", ""}, + {"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;", "", + ""}, + + // struct members and other oddities + {"struct S : public a::Foo {};", "struct S : public b::Bar {};", "", + ""}, + {"struct F { void f(a::Foo a1) {} };", + "struct F { void f(b::Bar a1) {} };", "", ""}, + {"struct F { a::Foo a_; };", "struct F { b::Bar a_; };", "", ""}, + {"struct F { ptr<a::Foo> a_; };", "struct F { ptr<b::Bar> a_; };", "", + ""}, + + {"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }", + "", ""}, + {"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }", + "", ""}, + {"void f() { a::Foo::Nested::NestedEnum e; }", + "void f() { b::Bar::Nested::NestedEnum e; }", "", ""}, + {"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }", + "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }", "", ""}, + {"void f() { auto e = a::Foo::Nested::E1; }", + "void f() { auto e = b::Bar::Nested::E1; }", "", ""}, + + // templates + {"template <typename T> struct Foo { T t; };\n" + "void f() { Foo<a::Foo> foo; }", + "template <typename T> struct Foo { T t; };\n" + "void f() { Foo<b::Bar> foo; }", + "", ""}, + {"template <typename T> struct Foo { a::Foo a; };", + "template <typename T> struct Foo { b::Bar a; };", "", ""}, + {"template <typename T> void f(T t) {}\n" + "void g() { f<a::Foo>(a::Foo()); }", + "template <typename T> void f(T t) {}\n" + "void g() { f<b::Bar>(b::Bar()); }", + "", ""}, + {"template <typename T> int f() { return 1; }\n" + "template <> int f<a::Foo>() { return 2; }\n" + "int g() { return f<a::Foo>(); }", + "template <typename T> int f() { return 1; }\n" + "template <> int f<b::Bar>() { return 2; }\n" + "int g() { return f<b::Bar>(); }", + "", ""}, + {"struct Foo { template <typename T> T foo(); };\n" + "void g() { Foo f; auto a = f.template foo<a::Foo>(); }", + "struct Foo { template <typename T> T foo(); };\n" + "void g() { Foo f; auto a = f.template foo<b::Bar>(); }", + "", ""}, + + // The following two templates are distilled from regressions found in + // unique_ptr<> and type_traits.h + {"template <typename T> struct outer {\n" + " typedef T type;\n" + " type Baz();\n" + " };\n" + " outer<a::Foo> g_A;", + "template <typename T> struct outer {\n" + " typedef T type;\n" + " type Baz();\n" + " };\n" + " outer<b::Bar> g_A;", + "", ""}, + {"template <typename T> struct nested { typedef T type; };\n" + "template <typename T> struct outer { typename nested<T>::type Foo(); " + "};\n" + "outer<a::Foo> g_A;", + "template <typename T> struct nested { typedef T type; };\n" + "template <typename T> struct outer { typename nested<T>::type Foo(); " + "};\n" + "outer<b::Bar> g_A;", + "", ""}, + + // macros + {"#define FOO(T, t) T t\n" + "void f() { FOO(a::Foo, a1); FOO(a::Foo, a2); }", + "#define FOO(T, t) T t\n" + "void f() { FOO(b::Bar, a1); FOO(b::Bar, a2); }", + "", ""}, + {"#define FOO(n) a::Foo n\n" + " void f() { FOO(a1); FOO(a2); }", + "#define FOO(n) b::Bar n\n" + " void f() { FOO(a1); FOO(a2); }", + "", ""}, + + // Pointer to member functions + {"auto gA = &a::Foo::func;", "auto gA = &b::Bar::func;", "", ""}, + {"using a::Foo; auto gA = &Foo::func;", + "using b::Bar; auto gA = &b::Bar::func;", "", ""}, + {"using a::Foo; namespace x { auto gA = &Foo::func; }", + "using b::Bar; namespace x { auto gA = &Bar::func; }", "", ""}, + {"typedef a::Foo T; auto gA = &T::func;", + "typedef b::Bar T; auto gA = &T::func;", "", ""}, + {"auto gA = &MACRO(a::Foo)::func;", "auto gA = &MACRO(b::Bar)::func;", + "", ""}, + + // Short match inside a namespace + {"namespace a { void f(Foo a1) {} }", + "namespace a { void f(b::Bar a1) {} }", "", ""}, + + // Correct match. + {"using a::Foo; struct F { ptr<Foo> a_; };", + "using b::Bar; struct F { ptr<Bar> a_; };", "", ""}, + + // avoid false positives + {"void f(b::Foo a) {}", "void f(b::Foo a) {}", "", ""}, + {"namespace b { void f(Foo a) {} }", "namespace b { void f(Foo a) {} }", + "", ""}, + + // friends, everyone needs friends. + {"class Foo { int i; friend class a::Foo; };", + "class Foo { int i; friend class b::Bar; };", "", ""}, + })), ); + +TEST_P(RenameClassTest, RenameClasses) { + auto Param = GetParam(); + std::string OldName = Param.OldName.empty() ? "a::Foo" : Param.OldName; + std::string NewName = Param.NewName.empty() ? "b::Bar" : Param.NewName; + std::string Actual = runClangRenameOnCode(Param.Before, OldName, NewName); + CompareSnippets(Param.After, Actual); +} + +class NamespaceDetectionTest : public ClangRenameTest { +protected: + NamespaceDetectionTest() { + AppendToHeader(R"( + class Old {}; + namespace o1 { + class Old {}; + namespace o2 { + class Old {}; + namespace o3 { + class Old {}; + } // namespace o3 + } // namespace o2 + } // namespace o1 + )"); + } +}; + +INSTANTIATE_TEST_CASE_P( + RenameClassTest, NamespaceDetectionTest, + ::testing::ValuesIn(std::vector<Case>({ + // Test old and new namespace overlap. + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { New moo; } } }", + "o1::o2::o3::Old", "o1::o2::o3::New"}, + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { n3::New moo; } } }", + "o1::o2::o3::Old", "o1::o2::n3::New"}, + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { n2::n3::New moo; } } }", + "o1::o2::o3::Old", "o1::n2::n3::New"}, + {"namespace o1 { namespace o2 { Old moo; } }", + "namespace o1 { namespace o2 { New moo; } }", "::o1::o2::Old", + "::o1::o2::New"}, + {"namespace o1 { namespace o2 { Old moo; } }", + "namespace o1 { namespace o2 { n2::New moo; } }", "::o1::o2::Old", + "::o1::n2::New"}, + {"namespace o1 { namespace o2 { Old moo; } }", + "namespace o1 { namespace o2 { ::n1::n2::New moo; } }", + "::o1::o2::Old", "::n1::n2::New"}, + {"namespace o1 { namespace o2 { Old moo; } }", + "namespace o1 { namespace o2 { n1::n2::New moo; } }", "::o1::o2::Old", + "n1::n2::New"}, + + // Test old and new namespace with differing depths. + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { New moo; } } }", + "o1::o2::o3::Old", "::o1::New"}, + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { New moo; } } }", + "o1::o2::o3::Old", "::o1::o2::New"}, + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { New moo; } } }", + "o1::o2::o3::Old", "o1::New"}, + {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }", + "namespace o1 { namespace o2 { namespace o3 { New moo; } } }", + "o1::o2::o3::Old", "o1::o2::New"}, + {"Old moo;", "o1::New moo;", "::Old", "o1::New"}, + {"Old moo;", "o1::New moo;", "Old", "o1::New"}, + {"namespace o1 { ::Old moo; }", "namespace o1 { New moo; }", "Old", + "o1::New"}, + {"namespace o1 { namespace o2 { Old moo; } }", + "namespace o1 { namespace o2 { ::New moo; } }", "::o1::o2::Old", + "::New"}, + {"namespace o1 { namespace o2 { Old moo; } }", + "namespace o1 { namespace o2 { New moo; } }", "::o1::o2::Old", "New"}, + + // Test moving into the new namespace at different levels. + {"namespace n1 { namespace n2 { o1::o2::Old moo; } }", + "namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old", + "::n1::n2::New"}, + {"namespace n1 { namespace n2 { o1::o2::Old moo; } }", + "namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old", + "n1::n2::New"}, + {"namespace n1 { namespace n2 { o1::o2::Old moo; } }", + "namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old", + "::n1::o2::New"}, + {"namespace n1 { namespace n2 { o1::o2::Old moo; } }", + "namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old", + "n1::o2::New"}, + {"namespace n1 { namespace n2 { o1::o2::Old moo; } }", + "namespace n1 { namespace n2 { ::o1::o2::New moo; } }", + "::o1::o2::Old", "::o1::o2::New"}, + {"namespace n1 { namespace n2 { o1::o2::Old moo; } }", + "namespace n1 { namespace n2 { o1::o2::New moo; } }", "::o1::o2::Old", + "o1::o2::New"}, + + // Test friends declarations. + {"class Foo { friend class o1::Old; };", + "class Foo { friend class o1::New; };", "o1::Old", "o1::New"}, + {"class Foo { int i; friend class o1::Old; };", + "class Foo { int i; friend class ::o1::New; };", "::o1::Old", + "::o1::New"}, + {"namespace o1 { class Foo { int i; friend class Old; }; }", + "namespace o1 { class Foo { int i; friend class New; }; }", "o1::Old", + "o1::New"}, + {"namespace o1 { class Foo { int i; friend class Old; }; }", + "namespace o1 { class Foo { int i; friend class New; }; }", + "::o1::Old", "::o1::New"}, + })), ); + +TEST_P(NamespaceDetectionTest, RenameClasses) { + auto Param = GetParam(); + std::string Actual = + runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName); + CompareSnippets(Param.After, Actual); +} + +class TemplatedClassRenameTest : public ClangRenameTest { +protected: + TemplatedClassRenameTest() { + AppendToHeader(R"( + template <typename T> struct Old { + T t_; + T f() { return T(); }; + static T s(T t) { return t; } + }; + namespace ns { + template <typename T> struct Old { + T t_; + T f() { return T(); }; + static T s(T t) { return t; } + }; + } // namespace ns + + namespace o1 { + namespace o2 { + namespace o3 { + template <typename T> struct Old { + T t_; + T f() { return T(); }; + static T s(T t) { return t; } + }; + } // namespace o3 + } // namespace o2 + } // namespace o1 + )"); + } +}; + +INSTANTIATE_TEST_CASE_P( + RenameClassTests, TemplatedClassRenameTest, + ::testing::ValuesIn(std::vector<Case>({ + {"Old<int> gI; Old<bool> gB;", "New<int> gI; New<bool> gB;", "Old", + "New"}, + {"ns::Old<int> gI; ns::Old<bool> gB;", + "ns::New<int> gI; ns::New<bool> gB;", "ns::Old", "ns::New"}, + {"auto gI = &Old<int>::f; auto gB = &Old<bool>::f;", + "auto gI = &New<int>::f; auto gB = &New<bool>::f;", "Old", "New"}, + {"auto gI = &ns::Old<int>::f;", "auto gI = &ns::New<int>::f;", + "ns::Old", "ns::New"}, + + {"int gI = Old<int>::s(0); bool gB = Old<bool>::s(false);", + "int gI = New<int>::s(0); bool gB = New<bool>::s(false);", "Old", + "New"}, + {"int gI = ns::Old<int>::s(0); bool gB = ns::Old<bool>::s(false);", + "int gI = ns::New<int>::s(0); bool gB = ns::New<bool>::s(false);", + "ns::Old", "ns::New"}, + + {"struct S { Old<int*> o_; };", "struct S { New<int*> o_; };", "Old", + "New"}, + {"struct S { ns::Old<int*> o_; };", "struct S { ns::New<int*> o_; };", + "ns::Old", "ns::New"}, + + {"auto a = reinterpret_cast<Old<int>*>(new Old<int>);", + "auto a = reinterpret_cast<New<int>*>(new New<int>);", "Old", "New"}, + {"auto a = reinterpret_cast<ns::Old<int>*>(new ns::Old<int>);", + "auto a = reinterpret_cast<ns::New<int>*>(new ns::New<int>);", + "ns::Old", "ns::New"}, + {"auto a = reinterpret_cast<const Old<int>*>(new Old<int>);", + "auto a = reinterpret_cast<const New<int>*>(new New<int>);", "Old", + "New"}, + {"auto a = reinterpret_cast<const ns::Old<int>*>(new ns::Old<int>);", + "auto a = reinterpret_cast<const ns::New<int>*>(new ns::New<int>);", + "ns::Old", "ns::New"}, + + {"Old<bool>& foo();", "New<bool>& foo();", "Old", "New"}, + {"ns::Old<bool>& foo();", "ns::New<bool>& foo();", "ns::Old", + "ns::New"}, + {"o1::o2::o3::Old<bool>& foo();", "o1::o2::o3::New<bool>& foo();", + "o1::o2::o3::Old", "o1::o2::o3::New"}, + {"namespace ns { Old<bool>& foo(); }", + "namespace ns { New<bool>& foo(); }", "ns::Old", "ns::New"}, + {"const Old<bool>& foo();", "const New<bool>& foo();", "Old", "New"}, + {"const ns::Old<bool>& foo();", "const ns::New<bool>& foo();", + "ns::Old", "ns::New"}, + + // FIXME: figure out why this only works when Moo gets + // specialized at some point. + {"template <typename T> struct Moo { Old<T> o_; }; Moo<int> m;", + "template <typename T> struct Moo { New<T> o_; }; Moo<int> m;", "Old", + "New"}, + {"template <typename T> struct Moo { ns::Old<T> o_; }; Moo<int> m;", + "template <typename T> struct Moo { ns::New<T> o_; }; Moo<int> m;", + "ns::Old", "ns::New"}, + })), ); + +TEST_P(TemplatedClassRenameTest, RenameTemplateClasses) { + auto Param = GetParam(); + std::string Actual = + runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName); + CompareSnippets(Param.After, Actual); +} + +TEST_F(ClangRenameTest, RenameClassWithOutOfLineMembers) { + std::string Before = R"( + class Old { + public: + Old(); + ~Old(); + + Old* next(); + + private: + Old* next_; + }; + + Old::Old() {} + Old::~Old() {} + Old* Old::next() { return next_; } + )"; + std::string Expected = R"( + class New { + public: + New(); + ~New(); + + New* next(); + + private: + New* next_; + }; + + New::New() {} + New::~New() {} + New* New::next() { return next_; } + )"; + std::string After = runClangRenameOnCode(Before, "Old", "New"); + CompareSnippets(Expected, After); +} + +TEST_F(ClangRenameTest, RenameClassWithInlineMembers) { + std::string Before = R"( + class Old { + public: + Old() {} + ~Old() {} + + Old* next() { return next_; } + + private: + Old* next_; + }; + )"; + std::string Expected = R"( + class New { + public: + New() {} + ~New() {} + + New* next() { return next_; } + + private: + New* next_; + }; + )"; + std::string After = runClangRenameOnCode(Before, "Old", "New"); + CompareSnippets(Expected, After); +} + +// FIXME: no prefix qualifiers being added to the class definition and +// constructor. +TEST_F(ClangRenameTest, RenameClassWithNamespaceWithInlineMembers) { + std::string Before = R"( + namespace ns { + class Old { + public: + Old() {} + ~Old() {} + + Old* next() { return next_; } + + private: + Old* next_; + }; + } // namespace ns + )"; + std::string Expected = R"( + namespace ns { + class ns::New { + public: + ns::New() {} + ~New() {} + + New* next() { return next_; } + + private: + New* next_; + }; + } // namespace ns + )"; + std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New"); + CompareSnippets(Expected, After); +} + +// FIXME: no prefix qualifiers being added to the class definition and +// constructor. +TEST_F(ClangRenameTest, RenameClassWithNamespaceWithOutOfInlineMembers) { + std::string Before = R"( + namespace ns { + class Old { + public: + Old(); + ~Old(); + + Old* next(); + + private: + Old* next_; + }; + + Old::Old() {} + Old::~Old() {} + Old* Old::next() { return next_; } + } // namespace ns + )"; + std::string Expected = R"( + namespace ns { + class ns::New { + public: + ns::New(); + ~New(); + + New* next(); + + private: + New* next_; + }; + + New::ns::New() {} + New::~New() {} + New* New::next() { return next_; } + } // namespace ns + )"; + std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New"); + CompareSnippets(Expected, After); +} + +// FIXME: no prefix qualifiers being added to the definition. +TEST_F(ClangRenameTest, RenameClassInInheritedConstructor) { + // `using Base::Base;` will generate an implicit constructor containing usage + // of `::ns::Old` which should not be matched. + std::string Before = R"( + namespace ns { + class Old { + int x; + }; + class Base { + protected: + Old *moo_; + public: + Base(Old *moo) : moo_(moo) {} + }; + class Derived : public Base { + public: + using Base::Base; + }; + } // namespace ns + int main() { + ::ns::Old foo; + ::ns::Derived d(&foo); + return 0; + })"; + std::string Expected = R"( + namespace ns { + class ns::New { + int x; + }; + class Base { + protected: + New *moo_; + public: + Base(New *moo) : moo_(moo) {} + }; + class Derived : public Base { + public: + using Base::Base; + }; + } // namespace ns + int main() { + ::ns::New foo; + ::ns::Derived d(&foo); + return 0; + })"; + std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New"); + CompareSnippets(Expected, After); +} + +TEST_F(ClangRenameTest, DontRenameReferencesInImplicitFunction) { + std::string Before = R"( + namespace ns { + class Old { + }; + } // namespace ns + struct S { + int y; + ns::Old old; + }; + void f() { + S s1, s2, s3; + // This causes an implicit assignment operator to be created. + s1 = s2 = s3; + } + )"; + std::string Expected = R"( + namespace ns { + class ::new_ns::New { + }; + } // namespace ns + struct S { + int y; + ::new_ns::New old; + }; + void f() { + S s1, s2, s3; + // This causes an implicit assignment operator to be created. + s1 = s2 = s3; + } + )"; + std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New"); + CompareSnippets(Expected, After); +} + +// FIXME: no prefix qualifiers being adding to the definition. +TEST_F(ClangRenameTest, ReferencesInLambdaFunctionParameters) { + std::string Before = R"( + template <class T> + class function; + template <class R, class... ArgTypes> + class function<R(ArgTypes...)> { + public: + template <typename Functor> + function(Functor f) {} + + function() {} + + R operator()(ArgTypes...) const {} + }; + + namespace ns { + class Old {}; + void f() { + function<void(Old)> func; + } + } // namespace ns)"; + std::string Expected = R"( + template <class T> + class function; + template <class R, class... ArgTypes> + class function<R(ArgTypes...)> { + public: + template <typename Functor> + function(Functor f) {} + + function() {} + + R operator()(ArgTypes...) const {} + }; + + namespace ns { + class ::new_ns::New {}; + void f() { + function<void(::new_ns::New)> func; + } + } // namespace ns)"; + std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New"); + CompareSnippets(Expected, After); +} + +} // anonymous namespace +} // namespace test +} // namespace clang_rename +} // namesdpace clang diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt index b5af99bdfd6d..8ed35480cb88 100644 --- a/unittests/Tooling/CMakeLists.txt +++ b/unittests/Tooling/CMakeLists.txt @@ -11,6 +11,7 @@ if (MSVC) endif() add_clang_unittest(ToolingTests + CastExprTest.cpp CommentHandlerTest.cpp CompilationDatabaseTest.cpp FixItTest.cpp diff --git a/unittests/Tooling/CastExprTest.cpp b/unittests/Tooling/CastExprTest.cpp new file mode 100644 index 000000000000..5310c2125472 --- /dev/null +++ b/unittests/Tooling/CastExprTest.cpp @@ -0,0 +1,38 @@ +//===- unittest/Tooling/CastExprTest.cpp ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "TestVisitor.h" + +using namespace clang; + +namespace { + +struct CastExprVisitor : TestVisitor<CastExprVisitor> { + std::function<void(ExplicitCastExpr *)> OnExplicitCast; + + bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) { + if (OnExplicitCast) + OnExplicitCast(Expr); + return true; + } +}; + +TEST(CastExprTest, GetSubExprAsWrittenThroughMaterializedTemporary) { + CastExprVisitor Visitor; + Visitor.OnExplicitCast = [](ExplicitCastExpr *Expr) { + auto Sub = Expr->getSubExprAsWritten(); + EXPECT_TRUE(isa<DeclRefExpr>(Sub)) + << "Expected DeclRefExpr, but saw " << Sub->getStmtClassName(); + }; + Visitor.runOver("struct S1 {};\n" + "struct S2 { operator S1(); };\n" + "S1 f(S2 s) { return static_cast<S1>(s); }\n"); +} + +} diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp index 5a6693eb4dbb..fd8afe6b7976 100644 --- a/unittests/Tooling/CompilationDatabaseTest.cpp +++ b/unittests/Tooling/CompilationDatabaseTest.cpp @@ -586,6 +586,27 @@ TEST(ParseFixedCompilationDatabase, HandlesPositionalArgs) { EXPECT_EQ(2, Argc); } +TEST(ParseFixedCompilationDatabase, HandlesPositionalArgsSyntaxOnly) { + // Adjust the given command line arguments to ensure that any positional + // arguments in them are stripped. + const char *Argv[] = {"--", "somefile.cpp", "-fsyntax-only", "-DDEF3"}; + int Argc = llvm::array_lengthof(Argv); + std::string ErrorMessage; + std::unique_ptr<CompilationDatabase> Database = + FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMessage); + ASSERT_TRUE((bool)Database); + ASSERT_TRUE(ErrorMessage.empty()); + std::vector<CompileCommand> Result = Database->getCompileCommands("source"); + ASSERT_EQ(1ul, Result.size()); + ASSERT_EQ(".", Result[0].Directory); + std::vector<std::string> Expected; + Expected.push_back("clang-tool"); + Expected.push_back("-fsyntax-only"); + Expected.push_back("-DDEF3"); + Expected.push_back("source"); + ASSERT_EQ(Expected, Result[0].CommandLine); +} + TEST(ParseFixedCompilationDatabase, HandlesArgv0) { const char *Argv[] = {"1", "2", "--", "mytool", "somefile.cpp"}; int Argc = sizeof(Argv) / sizeof(char*); diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp index 269bdbb34ab1..74c9c3db34d8 100644 --- a/unittests/Tooling/RecursiveASTVisitorTest.cpp +++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -158,4 +158,90 @@ TEST(RecursiveASTVisitor, DefaultArgumentsAreVisited) { "static int k = f();\n")); } +// Check to ensure that InitListExpr is visited twice, once each for the +// syntactic and semantic form. +class InitListExprPreOrderVisitor + : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> { +public: + bool VisitInitListExpr(InitListExpr *ILE) { + Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart()); + return true; + } +}; + +class InitListExprPostOrderVisitor + : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> { +public: + bool shouldTraversePostOrder() const { return true; } + + bool VisitInitListExpr(InitListExpr *ILE) { + Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart()); + return true; + } +}; + +class InitListExprPreOrderNoQueueVisitor + : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> { +public: + bool TraverseInitListExpr(InitListExpr *ILE) { + return ExpectedLocationVisitor::TraverseInitListExpr(ILE); + } + + bool VisitInitListExpr(InitListExpr *ILE) { + Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart()); + return true; + } +}; + +class InitListExprPostOrderNoQueueVisitor + : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> { +public: + bool shouldTraversePostOrder() const { return true; } + + bool TraverseInitListExpr(InitListExpr *ILE) { + return ExpectedLocationVisitor::TraverseInitListExpr(ILE); + } + + bool VisitInitListExpr(InitListExpr *ILE) { + Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart()); + return true; + } +}; + +TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) { + InitListExprPreOrderVisitor Visitor; + Visitor.ExpectMatch("syntactic", 2, 21); + Visitor.ExpectMatch("semantic", 2, 21); + EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n" + "static struct S s = {.x = 0};\n", + InitListExprPreOrderVisitor::Lang_C)); +} + +TEST(RecursiveASTVisitor, InitListExprIsPostOrderVisitedTwice) { + InitListExprPostOrderVisitor Visitor; + Visitor.ExpectMatch("syntactic", 2, 21); + Visitor.ExpectMatch("semantic", 2, 21); + EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n" + "static struct S s = {.x = 0};\n", + InitListExprPostOrderVisitor::Lang_C)); +} + +TEST(RecursiveASTVisitor, InitListExprIsPreOrderNoQueueVisitedTwice) { + InitListExprPreOrderNoQueueVisitor Visitor; + Visitor.ExpectMatch("syntactic", 2, 21); + Visitor.ExpectMatch("semantic", 2, 21); + EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n" + "static struct S s = {.x = 0};\n", + InitListExprPreOrderNoQueueVisitor::Lang_C)); +} + +TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) { + InitListExprPostOrderNoQueueVisitor Visitor; + Visitor.ExpectMatch("syntactic", 2, 21); + Visitor.ExpectMatch("semantic", 2, 21); + EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n" + "static struct S s = {.x = 0};\n", + InitListExprPostOrderNoQueueVisitor::Lang_C)); +} + } // end anonymous namespace diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp index 495ac755b39d..15900940c887 100644 --- a/unittests/Tooling/RefactoringTest.cpp +++ b/unittests/Tooling/RefactoringTest.cpp @@ -1123,8 +1123,10 @@ TEST_F(AtomicChangeTest, AtomicChangeToYAML) { "Key: 'input.cpp:20'\n" "FilePath: input.cpp\n" "Error: ''\n" - "InsertedHeaders: [ a.h ]\n" - "RemovedHeaders: [ b.h ]\n" + "InsertedHeaders: \n" // Extra whitespace here! + " - a.h\n" + "RemovedHeaders: \n" // Extra whitespace here! + " - b.h\n" "Replacements: \n" // Extra whitespace here! " - FilePath: input.cpp\n" " Offset: 20\n" @@ -1143,8 +1145,10 @@ TEST_F(AtomicChangeTest, YAMLToAtomicChange) { "Key: 'input.cpp:20'\n" "FilePath: input.cpp\n" "Error: 'ok'\n" - "InsertedHeaders: [ a.h ]\n" - "RemovedHeaders: [ b.h ]\n" + "InsertedHeaders: \n" // Extra whitespace here! + " - a.h\n" + "RemovedHeaders: \n" // Extra whitespace here! + " - b.h\n" "Replacements: \n" // Extra whitespace here! " - FilePath: input.cpp\n" " Offset: 20\n" diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h index a762ec8b1453..adfd3ef60f50 100644 --- a/unittests/Tooling/TestVisitor.h +++ b/unittests/Tooling/TestVisitor.h @@ -53,7 +53,10 @@ public: bool runOver(StringRef Code, Language L = Lang_CXX) { std::vector<std::string> Args; switch (L) { - case Lang_C: Args.push_back("-std=c99"); break; + case Lang_C: + Args.push_back("-x"); + Args.push_back("c"); + break; case Lang_CXX98: Args.push_back("-std=c++98"); break; case Lang_CXX11: Args.push_back("-std=c++11"); break; case Lang_CXX14: Args.push_back("-std=c++14"); break; diff --git a/utils/bash-autocomplete.sh b/utils/bash-autocomplete.sh index ba908bcc0bc3..775b1f45351a 100755 --- a/utils/bash-autocomplete.sh +++ b/utils/bash-autocomplete.sh @@ -1,7 +1,7 @@ # Please add "source /path/to/bash-autocomplete.sh" to your .bashrc to use this. _clang() { - local cur prev words cword arg + local cur prev words cword arg flags _init_completion -n : || return # bash always separates '=' as a token even if there's no space before/after '='. @@ -24,7 +24,14 @@ _clang() arg="$w2=,$cur" fi - local flags=$( clang --autocomplete="$arg" ) + flags=$( "${COMP_WORDS[0]}" --autocomplete="$arg" 2>/dev/null ) + # If clang is old that it does not support --autocomplete, + # fall back to the filename completion. + if [[ "$?" != 0 ]]; then + _filedir + return + fi + if [[ "$cur" == '=' ]]; then COMPREPLY=( $( compgen -W "$flags" -- "") ) elif [[ "$flags" == "" || "$arg" == "" ]]; then |