diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/bindings/python/clang/cindex.py llvm-toolchain-snapshot-6.0~svn316003/clang/bindings/python/clang/cindex.py --- llvm-toolchain-snapshot-6.0~svn314833/clang/bindings/python/clang/cindex.py 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/bindings/python/clang/cindex.py 2017-10-17 14:41:54.000000000 +0000 @@ -1587,6 +1587,16 @@ return StorageClass.from_id(self._storage_class) @property + def availability(self): + """ + Retrieves the availability of the entity pointed at by the cursor. + """ + if not hasattr(self, '_availability'): + self._availability = conf.lib.clang_getCursorAvailability(self) + + return AvailabilityKind.from_id(self._availability) + + @property def access_specifier(self): """ Retrieves the access specifier (if any) of the entity pointed at by the @@ -1923,6 +1933,24 @@ StorageClass.AUTO = StorageClass(6) StorageClass.REGISTER = StorageClass(7) +### Availability Kinds ### + +class AvailabilityKind(BaseEnumeration): + """ + Describes the availability of an entity. + """ + + # The unique kind objects, indexed by id. + _kinds = [] + _name_map = None + + def __repr__(self): + return 'AvailabilityKind.%s' % (self.name,) + +AvailabilityKind.AVAILABLE = AvailabilityKind(0) +AvailabilityKind.DEPRECATED = AvailabilityKind(1) +AvailabilityKind.NOT_AVAILABLE = AvailabilityKind(2) +AvailabilityKind.NOT_ACCESSIBLE = AvailabilityKind(3) ### C++ access specifiers ### @@ -3491,6 +3519,10 @@ [TranslationUnit, SourceLocation], Cursor), + ("clang_getCursorAvailability", + [Cursor], + c_int), + ("clang_getCursorDefinition", [Cursor], Cursor, @@ -4106,6 +4138,7 @@ register_enumerations() __all__ = [ + 'AvailabilityKind', 'Config', 'CodeCompletionResults', 'CompilationDatabase', diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/bindings/python/tests/cindex/test_cursor.py llvm-toolchain-snapshot-6.0~svn316003/clang/bindings/python/tests/cindex/test_cursor.py --- llvm-toolchain-snapshot-6.0~svn314833/clang/bindings/python/tests/cindex/test_cursor.py 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/bindings/python/tests/cindex/test_cursor.py 2017-10-17 14:41:54.000000000 +0000 @@ -1,6 +1,7 @@ import ctypes import gc +from clang.cindex import AvailabilityKind from clang.cindex import CursorKind from clang.cindex import TemplateArgumentKind from clang.cindex import TranslationUnit @@ -377,6 +378,26 @@ else: assert False, "Couldn't find annotation" +def test_annotation_template(): + annotation = '__attribute__ ((annotate("annotation")))' + for source, kind in [ + ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE), + ('class %s foo {};', CursorKind.CLASS_TEMPLATE), + ]: + source = 'template ' + (source % annotation) + tu = get_tu(source, lang="cpp") + + foo = get_cursor(tu, 'foo') + assert foo is not None + assert foo.kind == kind + + for c in foo.get_children(): + if c.kind == CursorKind.ANNOTATE_ATTR: + assert c.displayname == "annotation" + break + else: + assert False, "Couldn't find annotation for {}".format(kind) + def test_result_type(): tu = get_tu('int foo();') foo = get_cursor(tu, 'foo') @@ -385,6 +406,30 @@ t = foo.result_type assert t.kind == TypeKind.INT +def test_availability(): + tu = get_tu('class A { A(A const&) = delete; };', lang='cpp') + + # AvailabilityKind.AVAILABLE + cursor = get_cursor(tu, 'A') + assert cursor.kind == CursorKind.CLASS_DECL + assert cursor.availability == AvailabilityKind.AVAILABLE + + # AvailabilityKind.NOT_AVAILABLE + cursors = get_cursors(tu, 'A') + for c in cursors: + if c.kind == CursorKind.CONSTRUCTOR: + assert c.availability == AvailabilityKind.NOT_AVAILABLE + break + else: + assert False, "Could not find cursor for deleted constructor" + + # AvailabilityKind.DEPRECATED + tu = get_tu('void test() __attribute__((deprecated));', lang='cpp') + cursor = get_cursor(tu, 'test') + assert cursor.availability == AvailabilityKind.DEPRECATED + + # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results + def test_get_tokens(): """Ensure we can map cursors back to tokens.""" tu = get_tu('int foo(int i);') diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/cmake/caches/Apple-stage1.cmake llvm-toolchain-snapshot-6.0~svn316003/clang/cmake/caches/Apple-stage1.cmake --- llvm-toolchain-snapshot-6.0~svn314833/clang/cmake/caches/Apple-stage1.cmake 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/cmake/caches/Apple-stage1.cmake 2017-10-17 14:41:54.000000000 +0000 @@ -24,6 +24,12 @@ CMAKE_OSX_ARCHITECTURES CACHE STRING "") +# Disabling embedded darwin compiler-rt on stage1 builds is required because we +# don't build stage1 to support arm code generation. +set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "") +set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "") +set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") + set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") @@ -39,6 +45,8 @@ clang-test-depends distribution install-distribution + install-xcode-toolchain + install-distribution-toolchain clang CACHE STRING "") #bootstrap diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/cmake/caches/Apple-stage2.cmake llvm-toolchain-snapshot-6.0~svn316003/clang/cmake/caches/Apple-stage2.cmake --- llvm-toolchain-snapshot-6.0~svn314833/clang/cmake/caches/Apple-stage2.cmake 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/cmake/caches/Apple-stage2.cmake 2017-10-17 14:41:54.000000000 +0000 @@ -40,6 +40,10 @@ set(LIBCXX_INCLUDE_TESTS OFF CACHE BOOL "") set(LLVM_LTO_VERSION_OFFSET 3000 CACHE STRING "") +# Generating Xcode toolchains is useful for developers wanting to build and use +# clang without installing over existing tools. +set(LLVM_CREATE_XCODE_TOOLCHAIN ON CACHE BOOL "") + # setup toolchain set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "") set(LLVM_TOOLCHAIN_TOOLS diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/cmake/modules/ProtobufMutator.cmake llvm-toolchain-snapshot-6.0~svn316003/clang/cmake/modules/ProtobufMutator.cmake --- llvm-toolchain-snapshot-6.0~svn314833/clang/cmake/modules/ProtobufMutator.cmake 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/cmake/modules/ProtobufMutator.cmake 2017-10-17 14:41:54.000000000 +0000 @@ -6,7 +6,7 @@ ExternalProject_Add(${PBM_PREFIX} PREFIX ${PBM_PREFIX} GIT_REPOSITORY https://github.com/google/libprotobuf-mutator.git - GIT_TAG 17789d1 + GIT_TAG e4eae60 CONFIGURE_COMMAND ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/CMakeLists.txt llvm-toolchain-snapshot-6.0~svn316003/clang/CMakeLists.txt --- llvm-toolchain-snapshot-6.0~svn314833/clang/CMakeLists.txt 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/CMakeLists.txt 2017-10-17 14:41:54.000000000 +0000 @@ -235,6 +235,17 @@ set(CLANG_DEFAULT_OPENMP_RUNTIME "libomp" CACHE STRING "Default OpenMP runtime used by -fopenmp.") +# OpenMP offloading requires at least sm_30 because we use shuffle instructions +# to generate efficient code for reductions. +set(CLANG_OPENMP_NVPTX_DEFAULT_ARCH "sm_30" CACHE STRING + "Default architecture for OpenMP offloading to Nvidia GPUs.") +string(REGEX MATCH "^sm_([0-9]+)$" MATCHED_ARCH "${CLANG_OPENMP_NVPTX_DEFAULT_ARCH}") +if (NOT DEFINED MATCHED_ARCH OR "${CMAKE_MATCH_1}" LESS 30) + message(WARNING "Resetting default architecture for OpenMP offloading to Nvidia GPUs to sm_30") + set(CLANG_OPENMP_NVPTX_DEFAULT_ARCH "sm_30" CACHE STRING + "Default architecture for OpenMP offloading to Nvidia GPUs." FORCE) +endif() + set(CLANG_VENDOR ${PACKAGE_VENDOR} CACHE STRING "Vendor-specific text for showing with version information.") diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/docs/ClangFormatStyleOptions.rst llvm-toolchain-snapshot-6.0~svn316003/clang/docs/ClangFormatStyleOptions.rst --- llvm-toolchain-snapshot-6.0~svn314833/clang/docs/ClangFormatStyleOptions.rst 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/docs/ClangFormatStyleOptions.rst 2017-10-17 14:41:54.000000000 +0000 @@ -266,9 +266,13 @@ .. code-block:: c++ - true: false: - int a; // My comment a vs. int a; // My comment a - int b = 2; // comment b int b = 2; // comment about b + true: + int a; // My comment a + int b = 2; // comment b + + false: + int a; // My comment a + int b = 2; // comment about b **AllowAllParametersOfDeclarationOnNextLine** (``bool``) If the function declaration doesn't fit on a line, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/docs/InternalsManual.rst llvm-toolchain-snapshot-6.0~svn316003/clang/docs/InternalsManual.rst --- llvm-toolchain-snapshot-6.0~svn314833/clang/docs/InternalsManual.rst 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/docs/InternalsManual.rst 2017-10-17 14:41:54.000000000 +0000 @@ -1540,7 +1540,7 @@ After trying several different approaches, we've finally converged on a design (Note, at the time of this writing, not all of this has been implemented, consider this a design goal!). Our basic approach is to define a single -recursive method evaluation method (``Expr::Evaluate``), which is implemented +recursive evaluation method (``Expr::Evaluate``), which is implemented in ``AST/ExprConstant.cpp``. Given an expression with "scalar" type (integer, fp, complex, or pointer) this method returns the following information: @@ -2037,7 +2037,7 @@ * ``CodeGenFunction`` contains functions ``ConvertType`` and ``ConvertTypeForMem`` that convert Clang's types (``clang::Type*`` or ``clang::QualType``) to LLVM types. Use the former for values, and the - later for memory locations: test with the C++ "``bool``" type to check + latter for memory locations: test with the C++ "``bool``" type to check this. If you find that you are having to use LLVM bitcasts to make the subexpressions of your expression have the type that your expression expects, STOP! Go fix semantic analysis and the AST so that you don't diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/docs/RefactoringEngine.rst llvm-toolchain-snapshot-6.0~svn316003/clang/docs/RefactoringEngine.rst --- llvm-toolchain-snapshot-6.0~svn314833/clang/docs/RefactoringEngine.rst 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/docs/RefactoringEngine.rst 2017-10-17 14:41:54.000000000 +0000 @@ -41,7 +41,7 @@ public: StringRef getCommand() const override { return "local-rename"; } - StringRef getDescription() const override { + StringRef getDescription() const override { return "Finds and renames symbols in code with no indexer support"; } @@ -143,7 +143,7 @@ Rules.push_back( createRefactoringActionRule( SourceRangeSelectionRequirement()) - ) + ); The ``createRefactoringActionRule`` function takes in a list of refactoring action rule requirement values. These values describe the initiation diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/docs/ReleaseNotes.rst llvm-toolchain-snapshot-6.0~svn316003/clang/docs/ReleaseNotes.rst --- llvm-toolchain-snapshot-6.0~svn314833/clang/docs/ReleaseNotes.rst 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/docs/ReleaseNotes.rst 2017-10-17 14:41:54.000000000 +0000 @@ -78,6 +78,10 @@ when the signed integer is coerced to an unsigned type for the comparison. ``-Wsign-compare`` was adjusted not to warn in this case. +- ``-Wtautological-constant-compare`` is a new warning that warns on + tautological comparisons between integer variable of the type ``T`` and the + largest/smallest possible integer constant of that same type. + - ``-Wnull-pointer-arithmetic`` now warns about performing pointer arithmetic on a null pointer. Such pointer arithmetic has an undefined behavior if the offset is nonzero. It also now warns about arithmetic on a null pointer @@ -89,6 +93,11 @@ - Bitrig OS was merged back into OpenBSD, so Bitrig support has been removed from Clang/LLVM. +- The default value of _MSC_VER was raised from 1800 to 1911, making it + compatible with the Visual Studio 2015 and 2017 C++ standard library headers. + Users should generally expect this to be regularly raised to match the most + recently released version of the Visual C++ compiler. + New Compiler Flags ------------------ diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h 2017-10-17 14:41:54.000000000 +0000 @@ -909,15 +909,10 @@ public: static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } - Project(SExpr *R, StringRef SName) - : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr) - { } Project(SExpr *R, const clang::ValueDecl *Cvd) - : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd) - { } - Project(const Project &P, SExpr *R) - : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl) - { } + : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) { + assert(Cvd && "ValueDecl must not be null"); + } SExpr *record() { return Rec; } const SExpr *record() const { return Rec; } @@ -931,10 +926,14 @@ } StringRef slotName() const { - if (Cvdecl) + if (Cvdecl->getDeclName().isIdentifier()) return Cvdecl->getName(); - else - return SlotName; + if (!SlotName) { + SlotName = ""; + llvm::raw_string_ostream OS(*SlotName); + Cvdecl->printName(OS); + } + return *SlotName; } template @@ -953,7 +952,7 @@ private: SExpr* Rec; - StringRef SlotName; + mutable llvm::Optional SlotName; const clang::ValueDecl *Cvdecl; }; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/ASTContext.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/ASTContext.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/ASTContext.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/ASTContext.h 2017-10-17 14:41:54.000000000 +0000 @@ -496,7 +496,7 @@ CXXABI *createCXXABI(const TargetInfo &T); /// \brief The logical -> physical address space map. - const LangAS::Map *AddrSpaceMap; + const LangASMap *AddrSpaceMap; /// \brief Address space map mangling must be used with language specific /// address spaces (e.g. OpenCL/CUDA) @@ -1070,7 +1070,7 @@ /// The resulting type has a union of the qualifiers from T and the address /// space. If T already has an address space specifier, it is silently /// replaced. - QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; + QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const; /// \brief Remove any existing address space on the type and returns the type /// with qualifiers intact (or that's the idea anyway) @@ -2363,14 +2363,14 @@ return getTargetAddressSpace(Q.getAddressSpace()); } - unsigned getTargetAddressSpace(unsigned AS) const; + unsigned getTargetAddressSpace(LangAS AS) const; /// Get target-dependent integer value for null pointer which is used for /// constant folding. uint64_t getTargetNullPointerValue(QualType QT) const; - bool addressSpaceMapManglingFor(unsigned AS) const { - return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace; + bool addressSpaceMapManglingFor(LangAS AS) const { + return AddrSpaceMapMangling || isTargetAddressSpace(AS); } private: diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/ASTMutationListener.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/ASTMutationListener.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/ASTMutationListener.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/ASTMutationListener.h 2017-10-17 14:41:54.000000000 +0000 @@ -22,6 +22,7 @@ class CXXRecordDecl; class Decl; class DeclContext; + class Expr; class FieldDecl; class FunctionDecl; class FunctionTemplateDecl; @@ -80,7 +81,8 @@ /// \brief A virtual destructor's operator delete has been resolved. virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) {} + const FunctionDecl *Delete, + Expr *ThisArg) {} /// \brief An implicit member got a definition. virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/CharUnits.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/CharUnits.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/CharUnits.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/CharUnits.h 2017-10-17 14:41:54.000000000 +0000 @@ -40,14 +40,14 @@ typedef int64_t QuantityType; private: - QuantityType Quantity; + QuantityType Quantity = 0; explicit CharUnits(QuantityType C) : Quantity(C) {} public: /// CharUnits - A default constructor. - CharUnits() : Quantity(0) {} + CharUnits() = default; /// Zero - Construct a CharUnits quantity of zero. static CharUnits Zero() { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/DeclBase.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/DeclBase.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/DeclBase.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/DeclBase.h 2017-10-17 14:41:54.000000000 +0000 @@ -738,6 +738,13 @@ return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule(); } + /// Get the module that owns this declaration for linkage purposes. + /// There only ever is such a module under the C++ Modules TS. + /// + /// \param IgnoreLinkage Ignore the linkage of the entity; assume that + /// all declarations in a global module fragment are unowned. + Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const; + /// \brief Determine whether this declaration might be hidden from name /// lookup. Note that the declaration might be visible even if this returns /// \c false, if the owning module is visible within the query context. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/DeclCXX.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/DeclCXX.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/DeclCXX.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/DeclCXX.h 2017-10-17 14:41:54.000000000 +0000 @@ -2566,7 +2566,10 @@ class CXXDestructorDecl : public CXXMethodDecl { void anchor() override; + // FIXME: Don't allocate storage for these except in the first declaration + // of a virtual destructor. FunctionDecl *OperatorDelete; + Expr *OperatorDeleteThisArg; CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -2574,7 +2577,7 @@ bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), - OperatorDelete(nullptr) { + OperatorDelete(nullptr), OperatorDeleteThisArg(nullptr) { setImplicit(isImplicitlyDeclared); } @@ -2587,10 +2590,13 @@ bool isImplicitlyDeclared); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); - void setOperatorDelete(FunctionDecl *OD); + void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); const FunctionDecl *getOperatorDelete() const { return getCanonicalDecl()->OperatorDelete; } + Expr *getOperatorDeleteThisArg() const { + return getCanonicalDecl()->OperatorDeleteThisArg; + } CXXDestructorDecl *getCanonicalDecl() override { return cast(FunctionDecl::getCanonicalDecl()); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/Decl.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/Decl.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/Decl.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/Decl.h 2017-10-17 14:41:54.000000000 +0000 @@ -339,6 +339,12 @@ return clang::isExternallyVisible(getLinkageInternal()); } + /// Determine whether this declaration can be redeclared in a + /// different translation unit. + bool isExternallyDeclarable() const { + return isExternallyVisible() && !getOwningModuleForLinkage(); + } + /// \brief Determines the visibility of this entity. Visibility getVisibility() const { return getLinkageAndVisibility().getVisibility(); @@ -379,10 +385,6 @@ return hasCachedLinkage(); } - /// Get the module that owns this declaration for linkage purposes. - /// There only ever is such a module under the C++ Modules TS. - Module *getOwningModuleForLinkage() const; - /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl() { @@ -2034,6 +2036,9 @@ /// true through IsAligned. bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const; + /// \brief Determine whether this is a destroying operator delete. + bool isDestroyingOperatorDelete() const; + /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/Type.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/Type.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/AST/Type.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/AST/Type.h 2017-10-17 14:41:54.000000000 +0000 @@ -162,8 +162,6 @@ FastMask = (1 << FastWidth) - 1 }; - Qualifiers() : Mask(0) {} - /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { @@ -330,9 +328,11 @@ } bool hasAddressSpace() const { return Mask & AddressSpaceMask; } - unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + LangAS getAddressSpace() const { + return static_cast(Mask >> AddressSpaceShift); + } bool hasTargetSpecificAddressSpace() const { - return getAddressSpace() >= LangAS::FirstTargetAddressSpace; + return isTargetAddressSpace(getAddressSpace()); } /// Get the address space attribute value to be printed by diagnostics. unsigned getAddressSpaceAttributePrintValue() const { @@ -340,22 +340,22 @@ // This function is not supposed to be used with language specific // address spaces. If that happens, the diagnostic message should consider // printing the QualType instead of the address space value. - assert(Addr == 0 || hasTargetSpecificAddressSpace()); - if (Addr) - return Addr - LangAS::FirstTargetAddressSpace; + assert(Addr == LangAS::Default || hasTargetSpecificAddressSpace()); + if (Addr != LangAS::Default) + return toTargetAddressSpace(Addr); // TODO: The diagnostic messages where Addr may be 0 should be fixed // since it cannot differentiate the situation where 0 denotes the default // address space or user specified __attribute__((address_space(0))). return 0; } - void setAddressSpace(unsigned space) { - assert(space <= MaxAddressSpace); + void setAddressSpace(LangAS space) { + assert((unsigned)space <= MaxAddressSpace); Mask = (Mask & ~AddressSpaceMask) | (((uint32_t) space) << AddressSpaceShift); } - void removeAddressSpace() { setAddressSpace(0); } - void addAddressSpace(unsigned space) { - assert(space); + void removeAddressSpace() { setAddressSpace(LangAS::Default); } + void addAddressSpace(LangAS space) { + assert(space != LangAS::Default); setAddressSpace(space); } @@ -539,7 +539,7 @@ // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31| // |C R V|U|GCAttr|Lifetime|AddressSpace| - uint32_t Mask; + uint32_t Mask = 0; static const uint32_t UMask = 0x8; static const uint32_t UShift = 3; @@ -634,7 +634,7 @@ friend class QualifierCollector; public: - QualType() {} + QualType() = default; QualType(const Type *Ptr, unsigned Quals) : Value(Ptr, Quals) {} @@ -1007,7 +1007,7 @@ } /// Return the address space of this type. - inline unsigned getAddressSpace() const; + inline LangAS getAddressSpace() const; /// Returns gc attribute of this type. inline Qualifiers::GC getObjCGCAttr() const; @@ -1232,7 +1232,7 @@ } bool hasAddressSpace() const { return Quals.hasAddressSpace(); } - unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + LangAS getAddressSpace() const { return Quals.getAddressSpace(); } const Type *getBaseType() const { return BaseType; } @@ -5656,7 +5656,7 @@ } /// Return the address space of this type. -inline unsigned QualType::getAddressSpace() const { +inline LangAS QualType::getAddressSpace() const { return getQualifiers().getAddressSpace(); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/AddressSpaces.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/AddressSpaces.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/AddressSpaces.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/AddressSpaces.h 2017-10-17 14:41:54.000000000 +0000 @@ -16,25 +16,26 @@ #ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H #define LLVM_CLANG_BASIC_ADDRESSSPACES_H -namespace clang { +#include -namespace LangAS { +namespace clang { /// \brief Defines the address space values used by the address space qualifier /// of QualType. /// -enum ID { +enum class LangAS : unsigned { // The default value 0 is the value used in QualType for the the situation - // where there is no address space qualifier. For most languages, this also - // corresponds to the situation where there is no address space qualifier in - // the source code, except for OpenCL, where the address space value 0 in - // QualType represents private address space in OpenCL source code. + // where there is no address space qualifier. Default = 0, // OpenCL specific address spaces. + // In OpenCL each l-value must have certain non-default address space, each + // r-value must have no address space (i.e. the default address space). The + // pointee of a pointer must have non-default address space. opencl_global, opencl_local, opencl_constant, + opencl_private, opencl_generic, // CUDA specific address spaces. @@ -50,9 +51,24 @@ /// The type of a lookup table which maps from language-specific address spaces /// to target-specific ones. -typedef unsigned Map[FirstTargetAddressSpace]; +typedef unsigned LangASMap[(unsigned)LangAS::FirstTargetAddressSpace]; + +/// \return whether \p AS is a target-specific address space rather than a +/// clang AST address space +inline bool isTargetAddressSpace(LangAS AS) { + return (unsigned)AS >= (unsigned)LangAS::FirstTargetAddressSpace; } +inline unsigned toTargetAddressSpace(LangAS AS) { + assert(isTargetAddressSpace(AS)); + return (unsigned)AS - (unsigned)LangAS::FirstTargetAddressSpace; } +inline LangAS getLangASFromTargetAS(unsigned TargetAS) { + return static_cast((TargetAS) + + (unsigned)LangAS::FirstTargetAddressSpace); +} + +} // namespace clang + #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/AllDiagnostics.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/AllDiagnostics.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/AllDiagnostics.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/AllDiagnostics.h 2017-10-17 14:41:54.000000000 +0000 @@ -25,6 +25,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Serialization/SerializationDiagnostic.h" +#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" namespace clang { template diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/AttrDocs.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/AttrDocs.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/AttrDocs.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/AttrDocs.td 2017-10-17 14:41:54.000000000 +0000 @@ -1290,6 +1290,7 @@ def ARMInterruptDocs : Documentation { let Category = DocCatFunction; + let Heading = "interrupt (ARM)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on ARM targets. This attribute may be attached to a function definition and @@ -1331,6 +1332,7 @@ def MipsInterruptDocs : Documentation { let Category = DocCatFunction; + let Heading = "interrupt (MIPS)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on MIPS targets. This attribute may be attached to a function definition and instructs @@ -1427,6 +1429,7 @@ def AVRInterruptDocs : Documentation { let Category = DocCatFunction; + let Heading = "interrupt (AVR)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt))`` attribute on AVR targets. This attribute may be attached to a function definition and instructs @@ -2787,59 +2790,6 @@ }]; } -def AnyX86InterruptDocs : Documentation { - let Category = DocCatFunction; - let Content = [{ -Clang supports the GNU style ``__attribute__((interrupt))`` attribute on -x86/x86-64 targets.The compiler generates function entry and exit sequences -suitable for use in an interrupt handler when this attribute is present. -The 'IRET' instruction, instead of the 'RET' instruction, is used to return -from interrupt or exception handlers. All registers, except for the EFLAGS -register which is restored by the 'IRET' instruction, are preserved by the -compiler. - -Any interruptible-without-stack-switch code must be compiled with --mno-red-zone since interrupt handlers can and will, because of the -hardware design, touch the red zone. - -1. interrupt handler must be declared with a mandatory pointer argument: - - .. code-block:: c - - struct interrupt_frame - { - uword_t ip; - uword_t cs; - uword_t flags; - uword_t sp; - uword_t ss; - }; - - __attribute__ ((interrupt)) - void f (struct interrupt_frame *frame) { - ... - } - -2. exception handler: - - The exception handler is very similar to the interrupt handler with - a different mandatory function signature: - - .. code-block:: c - - __attribute__ ((interrupt)) - void f (struct interrupt_frame *frame, uword_t error_code) { - ... - } - - and compiler pops 'ERROR_CODE' off stack before the 'IRET' instruction. - - The exception handler should only be used for exceptions which push an - error code and all other exceptions must use the interrupt handler. - The system will crash if the wrong handler is used. - }]; -} - def AnyX86NoCallerSavedRegistersDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Attributes.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Attributes.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Attributes.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Attributes.h 2017-10-17 14:41:54.000000000 +0000 @@ -26,6 +26,8 @@ Microsoft, // Is the identifier known as a C++-style attribute? CXX, + // Is the identifier known as a C-style attribute? + C, // Is the identifier known as a pragma attribute? Pragma }; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Attr.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Attr.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Attr.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Attr.td 2017-10-17 14:41:54.000000000 +0000 @@ -210,6 +210,10 @@ string Namespace = namespace; int Version = version; } +class C2x : Spelling { + string Namespace = namespace; +} + class Keyword : Spelling; class Pragma : Spelling { string Namespace = namespace; @@ -958,7 +962,7 @@ def Deprecated : InheritableAttr { let Spellings = [GCC<"deprecated">, Declspec<"deprecated">, - CXX11<"","deprecated", 201309>]; + CXX11<"","deprecated", 201309>, C2x<"", "deprecated">]; let Args = [StringArgument<"Message", 1>, // An optional string argument that enables us to provide a // Fix-It. @@ -2040,7 +2044,7 @@ let Subjects = SubjectList<[HasFunctionProto]>; let ParseKind = "Interrupt"; let HasCustomParsing = 1; - let Documentation = [AnyX86InterruptDocs]; + let Documentation = [Undocumented]; } def AnyX86NoCallerSavedRegisters : InheritableAttr, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsAArch64.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsAArch64.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsAArch64.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsAArch64.def 2017-10-17 14:41:54.000000000 +0000 @@ -14,6 +14,10 @@ // The format of this database matches clang/Basic/Builtins.def. +#if defined(BUILTIN) && !defined(LANGBUILTIN) +# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) +#endif + // In libgcc BUILTIN(__clear_cache, "vv*v*", "i") @@ -61,4 +65,9 @@ BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) + #undef BUILTIN +#undef LANGBUILTIN diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsAMDGPU.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsAMDGPU.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsAMDGPU.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsAMDGPU.def 2017-10-17 14:41:54.000000000 +0000 @@ -21,6 +21,7 @@ // SI+ only builtins. //===----------------------------------------------------------------------===// +BUILTIN(__builtin_amdgcn_dispatch_ptr, "Uc*2", "nc") BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "Uc*2", "nc") BUILTIN(__builtin_amdgcn_implicitarg_ptr, "Uc*2", "nc") @@ -120,6 +121,8 @@ // Special builtins. //===----------------------------------------------------------------------===// BUILTIN(__builtin_amdgcn_read_exec, "LUi", "nc") +BUILTIN(__builtin_amdgcn_read_exec_lo, "Ui", "nc") +BUILTIN(__builtin_amdgcn_read_exec_hi, "Ui", "nc") //===----------------------------------------------------------------------===// // R600-NI only builtins. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Builtins.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Builtins.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Builtins.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Builtins.def 2017-10-17 14:41:54.000000000 +0000 @@ -1008,9 +1008,9 @@ LIBBUILTIN(modff, "fff*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(modfl, "LdLdLd*", "fn", "math.h", ALL_LANGUAGES) -LIBBUILTIN(nan, "dcC*", "fnc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(nanf, "fcC*", "fnc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(nanl, "LdcC*", "fnc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nan, "dcC*", "fUn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nanf, "fcC*", "fUn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nanl, "LdcC*", "fUn", "math.h", ALL_LANGUAGES) LIBBUILTIN(pow, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(powf, "fff", "fne", "math.h", ALL_LANGUAGES) @@ -1434,6 +1434,9 @@ BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") +// OpenMP 4.0 +LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG) + // Builtins for XRay BUILTIN(__xray_customevent, "vcC*z", "") diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Builtins.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Builtins.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Builtins.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Builtins.h 2017-10-17 14:41:54.000000000 +0000 @@ -38,6 +38,7 @@ MS_LANG = 0x10, // builtin requires MS mode. OCLC20_LANG = 0x20, // builtin for OpenCL C 2.0 only. OCLC1X_LANG = 0x40, // builtin for OpenCL C 1.x only. + OMP_LANG = 0x80, // builtin requires OpenMP. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG, // builtin requires MS mode. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsNVPTX.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsNVPTX.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsNVPTX.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsNVPTX.def 2017-10-17 14:41:54.000000000 +0000 @@ -688,5 +688,18 @@ BUILTIN(__nvvm_ldg_f4, "E4fE4fC*", "") BUILTIN(__nvvm_ldg_d2, "E2dE2dC*", "") +// Builtins to support WMMA instructions on sm_70 +TARGET_BUILTIN(__hmma_m16n16k16_ld_a, "vi*iC*UiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_ld_b, "vi*iC*UiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f16, "vi*iC*UiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f32, "vf*fC*UiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_st_c_f16, "vi*i*UiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_st_c_f32, "vf*f*UiIi", "", "ptx60") + +TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", "ptx60") + #undef BUILTIN #undef TARGET_BUILTIN diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsX86.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsX86.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/BuiltinsX86.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/BuiltinsX86.def 2017-10-17 14:41:54.000000000 +0000 @@ -639,7 +639,10 @@ TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves") //CLFLUSHOPT -TARGET_BUILTIN(__builtin_ia32_clflushopt, "vc*", "", "clflushopt") +TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "", "clflushopt") + +//CLWB +TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "", "clwb") // ADX TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx") diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/CMakeLists.txt llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/CMakeLists.txt --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/CMakeLists.txt 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/CMakeLists.txt 2017-10-17 14:41:54.000000000 +0000 @@ -14,6 +14,7 @@ clang_diag_gen(Frontend) clang_diag_gen(Lex) clang_diag_gen(Parse) +clang_diag_gen(Refactoring) clang_diag_gen(Sema) clang_diag_gen(Serialization) clang_tablegen(DiagnosticGroups.inc -gen-clang-diag-groups diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticDriverKinds.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticDriverKinds.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticDriverKinds.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticDriverKinds.td 2017-10-17 14:41:54.000000000 +0000 @@ -330,4 +330,8 @@ "unable to find a Visual Studio installation; " "try running Clang from a developer command prompt">, InGroup>; + +def warn_drv_fine_grained_bitfield_accesses_ignored : Warning< + "option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored">, + InGroup; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticFrontendKinds.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticFrontendKinds.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticFrontendKinds.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticFrontendKinds.td 2017-10-17 14:41:54.000000000 +0000 @@ -116,6 +116,8 @@ "action %0 not compiled in">; def err_fe_invalid_alignment : Error< "invalid value '%1' in '%0'; alignment must be a power of 2">; +def err_fe_invalid_wchar_type + : Error<"invalid wchar_t type '%0'; must be one of 'char', 'short', 'int'">; def warn_fe_serialized_diag_merge_failure : Warning< "unable to merge a subprocess's serialized diagnostics">, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticGroups.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticGroups.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticGroups.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticGroups.td 2017-10-17 14:41:54.000000000 +0000 @@ -432,13 +432,15 @@ def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">; def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">; def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; +def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare", + [TautologicalUnsignedZeroCompare, + TautologicalUnsignedEnumZeroCompare, + TautologicalOutOfRangeCompare]>; def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">; def TautologicalCompare : DiagGroup<"tautological-compare", - [TautologicalUnsignedZeroCompare, - TautologicalUnsignedEnumZeroCompare, - TautologicalOutOfRangeCompare, + [TautologicalConstantCompare, TautologicalPointerCompare, TautologicalOverlapCompare, TautologicalUndefinedCompare]>; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticIDs.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticIDs.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticIDs.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticIDs.h 2017-10-17 14:41:54.000000000 +0000 @@ -38,7 +38,8 @@ DIAG_SIZE_COMMENT = 100, DIAG_SIZE_CROSSTU = 100, DIAG_SIZE_SEMA = 3500, - DIAG_SIZE_ANALYSIS = 100 + DIAG_SIZE_ANALYSIS = 100, + DIAG_SIZE_REFACTORING = 1000, }; // Start position for diagnostics. enum { @@ -53,7 +54,8 @@ DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_CROSSTU, DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_COMMENT, DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, - DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS + DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, + DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING }; class CustomDiagInfo; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticLexKinds.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticLexKinds.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticLexKinds.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticLexKinds.td 2017-10-17 14:41:54.000000000 +0000 @@ -346,6 +346,23 @@ def ext_pp_comma_expr : Extension<"comma operator in operand of #if">; def ext_pp_bad_vaargs_use : Extension< "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">; + +def ext_pp_bad_vaopt_use + : ExtWarn< + "__VA_OPT__ can only appear in the expansion of a variadic macro">, + InGroup; + +def err_pp_missing_lparen_in_vaopt_use : Error< + "missing '(' following __VA_OPT__">; +def err_pp_vaopt_nested_use : Error< + "__VA_OPT__ cannot be nested within its own replacement tokens">; + +def err_vaopt_paste_at_start : Error< + "'##' cannot appear at start of __VA_OPT__ argument">; + +def err_vaopt_paste_at_end + : Error<"'##' cannot appear at end of __VA_OPT__ argument">; + def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">, InGroup; def ext_variadic_macro : Extension<"variadic macros are a C99 feature">, InGroup; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticParseKinds.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticParseKinds.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticParseKinds.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticParseKinds.td 2017-10-17 14:41:54.000000000 +0000 @@ -558,10 +558,13 @@ def warn_cxx98_compat_nullptr : Warning< "'nullptr' is incompatible with C++98">, InGroup, DefaultIgnore; -def warn_cxx14_compat_attribute : Warning< +def ext_ns_enum_attribute : Extension< + "attributes on %select{a namespace|an enumerator}0 declaration are " + "a C++17 extension">, InGroup; +def warn_cxx14_compat_ns_enum_attribute : Warning< "attributes on %select{a namespace|an enumerator}0 declaration are " "incompatible with C++ standards before C++17">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticRefactoringKinds.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticRefactoringKinds.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticRefactoringKinds.td 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticRefactoringKinds.td 2017-10-17 14:41:54.000000000 +0000 @@ -0,0 +1,25 @@ +//==--- DiagnosticRefactoringKinds.td - refactoring diagnostics -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Refactoring Diagnostics +//===----------------------------------------------------------------------===// + +let Component = "Refactoring" in { + +let CategoryName = "Refactoring Invocation Issue" in { + +def err_refactor_no_selection : Error<"refactoring action can't be initiated " + "without a selection">; +def err_refactor_selection_no_symbol : Error<"there is no symbol at the given " + "location">; + +} + +} // end of Refactoring diagnostics diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticSemaKinds.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticSemaKinds.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/DiagnosticSemaKinds.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/DiagnosticSemaKinds.td 2017-10-17 14:41:54.000000000 +0000 @@ -355,7 +355,7 @@ "implicit declaration of function %0">, InGroup, DefaultIgnore; def ext_implicit_function_decl : ExtWarn< - "implicit declaration of function %0 is invalid in C99">, + "implicit declaration of function %0 is invalid in %select{C99|OpenCL}1">, InGroup; def note_function_suggestion : Note<"did you mean %0?">; @@ -366,8 +366,10 @@ def err_language_linkage_spec_not_ascii : Error< "string literal in language linkage specifier cannot have an " "encoding-prefix">; -def warn_use_out_of_scope_declaration : Warning< - "use of out-of-scope declaration of %0">; +def ext_use_out_of_scope_declaration : ExtWarn< + "use of out-of-scope declaration of %0%select{| whose type is not " + "compatible with that of an implicit declaration}1">, + InGroup>; def err_inline_non_function : Error< "'inline' can only appear on functions%select{| and non-local variables}0">; def err_noreturn_non_function : Error< @@ -4799,6 +4801,9 @@ def err_thread_thread_different_kind : Error< "thread-local declaration of %0 with %select{static|dynamic}1 initialization " "follows declaration with %select{dynamic|static}1 initialization">; +def err_mismatched_owning_module : Error< + "declaration of %0 in %select{the global module|module %2}1 follows " + "declaration in %select{the global module|module %4}3">; def err_redefinition_different_type : Error< "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; def err_redefinition_different_kind : Error< @@ -5933,18 +5938,18 @@ "member function %q1 is declared const here|" "%select{|nested }1data member %2 declared const here}0">; -def warn_lunsigned_always_true_comparison : Warning< - "comparison of unsigned expression %0 is always %select{false|true}1">, +def warn_unsigned_always_true_comparison : Warning< + "comparison of %select{%3|unsigned expression}0 %2 " + "%select{unsigned expression|%3}0 is always %select{false|true}4">, InGroup; -def warn_runsigned_always_true_comparison : Warning< - "comparison of %0 unsigned expression is always %select{false|true}1">, - InGroup; -def warn_lunsigned_enum_always_true_comparison : Warning< - "comparison of unsigned enum expression %0 is always %select{false|true}1">, - InGroup; -def warn_runsigned_enum_always_true_comparison : Warning< - "comparison of %0 unsigned enum expression is always %select{false|true}1">, +def warn_unsigned_enum_always_true_comparison : Warning< + "comparison of %select{%3|unsigned enum expression}0 %2 " + "%select{unsigned enum expression|%3}0 is always %select{false|true}4">, InGroup; +def warn_tautological_constant_compare : Warning< + "comparison %select{%3|%1}0 %2 " + "%select{%1|%3}0 is always %select{false|true}4">, + InGroup; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, @@ -7607,6 +7612,11 @@ "%0 cannot take a dependent type as first parameter; use %1 instead">; def err_operator_delete_param_type : Error< "first parameter of %0 must have type %1">; +def err_destroying_operator_delete_not_usual : Error< + "destroying operator delete can have only an optional size and optional " + "alignment parameter">; +def note_implicit_delete_this_in_destructor_here : Note< + "while checking implicit 'delete this' for virtual destructor">; // C++ literal operators def err_literal_operator_outside_namespace : Error< @@ -8447,8 +8457,6 @@ "element. (%0 and %1)">; def err_bad_kernel_param_type : Error< "%0 cannot be used as the type of a kernel parameter">; -def err_opencl_implicit_function_decl : Error< - "implicit declaration of function %0 is invalid in OpenCL">; def err_record_with_pointers_kernel_param : Error< "%select{struct|union}0 kernel parameters may not contain pointers">; def note_within_field_of_type : Note< @@ -8991,6 +8999,14 @@ "redefinition of module '%0'">; def note_prev_module_definition : Note<"previously defined here">; def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">; +def err_module_not_defined : Error< + "definition of module '%0' is not available; use -fmodule-file= to specify " + "path to precompiled module interface">; +def err_module_redeclaration : Error< + "translation unit contains multiple module declarations">; +def note_prev_module_declaration : Note<"previous module declaration is here">; +def err_module_declaration_missing : Error< + "missing 'export module' declaration in module interface unit">; def err_module_private_specialization : Error< "%select{template|partial|member}0 specialization cannot be " "declared __module_private__">; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Diagnostic.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Diagnostic.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/Diagnostic.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/Diagnostic.td 2017-10-17 14:41:54.000000000 +0000 @@ -138,6 +138,7 @@ include "DiagnosticFrontendKinds.td" include "DiagnosticLexKinds.td" include "DiagnosticParseKinds.td" +include "DiagnosticRefactoringKinds.td" include "DiagnosticSemaKinds.td" include "DiagnosticSerializationKinds.td" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/LangOptions.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/LangOptions.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/LangOptions.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/LangOptions.def 2017-10-17 14:41:54.000000000 +0000 @@ -137,6 +137,8 @@ LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS") LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments") +LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") + BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers") LANGOPT(POSIXThreads , 1, 0, "POSIX thread support") LANGOPT(Blocks , 1, 0, "blocks extension to C") @@ -175,7 +177,8 @@ BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") LANGOPT(CharIsSigned , 1, 1, "signed char") -LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") +LANGOPT(WCharSize , 4, 0, "width of wchar_t") +LANGOPT(WCharIsSigned , 1, 0, "signed or unsigned wchar_t") ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default calling convention") diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/LangOptions.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/LangOptions.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/LangOptions.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/LangOptions.h 2017-10-17 14:41:54.000000000 +0000 @@ -197,6 +197,10 @@ bool allowsNonTrivialObjCLifetimeQualifiers() const { return ObjCAutoRefCount || ObjCWeak; } + + bool assumeFunctionsAreConvergent() const { + return (CUDA && CUDAIsDevice) || OpenCL; + } }; /// \brief Floating point control options diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/SourceLocation.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/SourceLocation.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/SourceLocation.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/SourceLocation.h 2017-10-17 14:41:54.000000000 +0000 @@ -39,10 +39,9 @@ class FileID { /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is /// this module, and <-1 is something loaded from another module. - int ID; -public: - FileID() : ID(0) {} + int ID = 0; +public: bool isValid() const { return ID != 0; } bool isInvalid() const { return ID == 0; } @@ -86,17 +85,15 @@ /// /// It is important that this type remains small. It is currently 32 bits wide. class SourceLocation { - unsigned ID; + unsigned ID = 0; friend class SourceManager; friend class ASTReader; friend class ASTWriter; enum : unsigned { MacroIDBit = 1U << 31 }; -public: - - SourceLocation() : ID(0) {} +public: bool isFileID() const { return (ID & MacroIDBit) == 0; } bool isMacroID() const { return (ID & MacroIDBit) != 0; } @@ -198,8 +195,9 @@ class SourceRange { SourceLocation B; SourceLocation E; + public: - SourceRange(): B(SourceLocation()), E(SourceLocation()) {} + SourceRange() = default; SourceRange(SourceLocation loc) : B(loc), E(loc) {} SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} @@ -230,9 +228,10 @@ /// range. class CharSourceRange { SourceRange Range; - bool IsTokenRange; + bool IsTokenRange = false; + public: - CharSourceRange() : IsTokenRange(false) {} + CharSourceRange() = default; CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {} static CharSourceRange getTokenRange(SourceRange R) { @@ -330,10 +329,11 @@ /// /// This is useful for argument passing to functions that expect both objects. class FullSourceLoc : public SourceLocation { - const SourceManager *SrcMgr; + const SourceManager *SrcMgr = nullptr; + public: /// \brief Creates a FullSourceLoc where isValid() returns \c false. - explicit FullSourceLoc() : SrcMgr(nullptr) {} + FullSourceLoc() = default; explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/TargetInfo.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/TargetInfo.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Basic/TargetInfo.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Basic/TargetInfo.h 2017-10-17 14:41:54.000000000 +0000 @@ -86,7 +86,7 @@ *LongDoubleFormat, *Float128Format; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI TheCXXABI; - const LangAS::Map *AddrSpaceMap; + const LangASMap *AddrSpaceMap; mutable StringRef PlatformName; mutable VersionTuple PlatformMinVersion; @@ -322,9 +322,7 @@ /// \brief Get integer value for null pointer. /// \param AddrSpace address space of pointee in source language. - virtual uint64_t getNullPointerValue(unsigned AddrSpace) const { - return 0; - } + virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; } /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } @@ -971,15 +969,13 @@ return nullptr; } - const LangAS::Map &getAddressSpaceMap() const { - return *AddrSpaceMap; - } + const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; } /// \brief Return an AST address space which can be used opportunistically /// for constant global memory. It must be possible to convert pointers into /// this address space to LangAS::Default. If no such address space exists, /// this may return None, and such optimizations will be disabled. - virtual llvm::Optional getConstantAddressSpace() const { + virtual llvm::Optional getConstantAddressSpace() const { return LangAS::Default; } @@ -1058,7 +1054,7 @@ } /// \brief Get address space for OpenCL type. - virtual LangAS::ID getOpenCLTypeAddrSpace(const Type *T) const; + virtual LangAS getOpenCLTypeAddrSpace(const Type *T) const; /// \returns Target specific vtbl ptr address space. virtual unsigned getVtblPtrAddressSpace() const { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/CodeGen/CodeGenABITypes.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/CodeGen/CodeGenABITypes.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/CodeGen/CodeGenABITypes.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/CodeGen/CodeGenABITypes.h 2017-10-17 14:41:54.000000000 +0000 @@ -72,12 +72,19 @@ FunctionType::ExtInfo info, RequiredArgs args); -// Returns null if the function type is incomplete and can't be lowered. +/// Returns null if the function type is incomplete and can't be lowered. llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM, const FunctionDecl *FD); llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T); +/// Given a non-bitfield struct field, return its index within the elements of +/// the struct's converted type. The returned index refers to a field number in +/// the complete object type which is returned by convertTypeForMemory. FD must +/// be a field in RD directly (i.e. not an inherited field). +unsigned getLLVMFieldNumber(CodeGenModule &CGM, + const RecordDecl *RD, const FieldDecl *FD); + } // end namespace CodeGen } // end namespace clang diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Config/config.h.cmake llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Config/config.h.cmake --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Config/config.h.cmake 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Config/config.h.cmake 2017-10-17 14:41:54.000000000 +0000 @@ -20,6 +20,9 @@ /* Default OpenMP runtime used by -fopenmp. */ #define CLANG_DEFAULT_OPENMP_RUNTIME "${CLANG_DEFAULT_OPENMP_RUNTIME}" +/* Default architecture for OpenMP offloading to Nvidia GPUs. */ +#define CLANG_OPENMP_NVPTX_DEFAULT_ARCH "${CLANG_OPENMP_NVPTX_DEFAULT_ARCH}" + /* Multilib suffix for libdir. */ #define CLANG_LIBDIR_SUFFIX "${CLANG_LIBDIR_SUFFIX}" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/CC1Options.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/CC1Options.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/CC1Options.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/CC1Options.td 2017-10-17 14:41:54.000000000 +0000 @@ -709,6 +709,12 @@ HelpText<"Include the default header file for OpenCL">; def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">, HelpText<"Preserve 3-component vector type">; +def fwchar_type_EQ : Joined<["-"], "fwchar-type=">, + HelpText<"Select underlying type for wchar_t">, Values<"char,short,int">; +def fsigned_wchar : Flag<["-"], "fsigned-wchar">, + HelpText<"Use a signed type for wchar_t">; +def fno_signed_wchar : Flag<["-"], "fno-signed-wchar">, + HelpText<"Use an unsigned type for wchar_t">; // FIXME: Remove these entirely once functionality/tests have been excised. def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/Options.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/Options.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/Options.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/Options.td 2017-10-17 14:41:54.000000000 +0000 @@ -592,7 +592,9 @@ HelpText<"Use Apple's kernel extensions ABI">; def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group, Flags<[CC1Option]>, HelpText<"Enable Apple gcc-compatible #pragma pack handling">; -def shared_libasan : Flag<["-"], "shared-libasan">; +def shared_libsan : Flag<["-"], "shared-libsan">; +def static_libsan : Flag<["-"], "static-libsan">; +def : Flag<["-"], "shared-libasan">, Alias; def fasm : Flag<["-"], "fasm">, Group; def fasm_blocks : Flag<["-"], "fasm-blocks">, Group, Flags<[CC1Option]>; @@ -604,6 +606,13 @@ def fast : Flag<["-"], "fast">, Group; def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group; +def fdouble_square_bracket_attributes : Flag<[ "-" ], "fdouble-square-bracket-attributes">, + Group, Flags<[DriverOption, CC1Option]>, + HelpText<"Enable '[[]]' attributes in all C and C++ language modes">; +def fno_double_square_bracket_attributes : Flag<[ "-" ], "fno-fdouble-square-bracket-attributes">, + Group, Flags<[DriverOption]>, + HelpText<"Disable '[[]]' attributes in all C and C++ language modes">; + def fautolink : Flag <["-"], "fautolink">, Group; def fno_autolink : Flag <["-"], "fno-autolink">, Group, Flags<[DriverOption, CC1Option]>, @@ -1036,6 +1045,13 @@ Group, Flags<[CC1Option]>, HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; +def ffine_grained_bitfield_accesses : Flag<["-"], + "ffine-grained-bitfield-accesses">, Group, Flags<[CC1Option]>, + HelpText<"Use separate accesses for bitfields with legal widths and alignments.">; +def fno_fine_grained_bitfield_accesses : Flag<["-"], + "fno-fine-grained-bitfield-accesses">, Group, Flags<[CC1Option]>, + HelpText<"Use large-integer access for consecutive bitfield runs.">; + def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; @@ -1380,9 +1396,9 @@ def : Flag<["-"], "fsched-interblock">, Group; def fshort_enums : Flag<["-"], "fshort-enums">, Group, Flags<[CC1Option]>, HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; -def fshort_wchar : Flag<["-"], "fshort-wchar">, Group, Flags<[CC1Option]>, +def fshort_wchar : Flag<["-"], "fshort-wchar">, Group, HelpText<"Force wchar_t to be a short unsigned int">; -def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group, Flags<[CC1Option]>, +def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group, HelpText<"Force wchar_t to be an unsigned int">; def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group, Flags<[CC1Option]>, HelpText<"Which overload candidates to show when overload resolution fails: " diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/SanitizerArgs.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/SanitizerArgs.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/SanitizerArgs.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/SanitizerArgs.h 2017-10-17 14:41:54.000000000 +0000 @@ -33,7 +33,7 @@ bool MsanUseAfterDtor = false; bool CfiCrossDso = false; int AsanFieldPadding = 0; - bool AsanSharedRuntime = false; + bool SharedRuntime = false; bool AsanUseAfterScope = true; bool AsanGlobalsDeadStripping = false; bool LinkCXXRuntimes = false; @@ -44,13 +44,16 @@ bool TsanFuncEntryExit = true; bool TsanAtomics = true; bool MinimalRuntime = false; + // True if cross-dso CFI support if provided by the system (i.e. Android). + bool ImplicitCfiRuntime = false; public: /// Parses the sanitizer arguments from an argument list. SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); + bool needsSharedRt() const { return SharedRuntime; } + bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); } - bool needsSharedAsanRt() const { return AsanSharedRuntime; } bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/ToolChain.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/ToolChain.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Driver/ToolChain.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Driver/ToolChain.h 2017-10-17 14:41:54.000000000 +0000 @@ -245,14 +245,9 @@ /// TranslateOpenMPTargetArgs - Create a new derived argument list for /// that contains the OpenMP target specific flags passed via /// -Xopenmp-target -opt=val OR -Xopenmp-target= -opt=val - /// Translation occurs only when the \p DeviceOffloadKind is specified. - /// - /// \param DeviceOffloadKind - The device offload kind used for the - /// translation. virtual llvm::opt::DerivedArgList *TranslateOpenMPTargetArgs( - const llvm::opt::DerivedArgList &Args, - Action::OffloadKind DeviceOffloadKind, - SmallVector &AllocatedArgs) const; + const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, + SmallVectorImpl &AllocatedArgs) const; /// Choose a tool to use to handle the action \p JA. /// diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Frontend/CodeGenOptions.def llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Frontend/CodeGenOptions.def --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Frontend/CodeGenOptions.def 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Frontend/CodeGenOptions.def 2017-10-17 14:41:54.000000000 +0000 @@ -179,6 +179,7 @@ CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. +CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Frontend/CommandLineSourceLoc.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Frontend/CommandLineSourceLoc.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Frontend/CommandLineSourceLoc.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Frontend/CommandLineSourceLoc.h 2017-10-17 14:41:54.000000000 +0000 @@ -51,6 +51,52 @@ } }; +/// A source range that has been parsed on the command line. +struct ParsedSourceRange { + std::string FileName; + /// The starting location of the range. The first element is the line and + /// the second element is the column. + std::pair Begin; + /// The ending location of the range. The first element is the line and the + /// second element is the column. + std::pair End; + + /// Returns a parsed source range from a string or None if the string is + /// invalid. + /// + /// These source string has the following format: + /// + /// file:start_line:start_column[-end_line:end_column] + /// + /// If the end line and column are omitted, the starting line and columns + /// are used as the end values. + static Optional fromString(StringRef Str) { + std::pair RangeSplit = Str.rsplit('-'); + unsigned EndLine, EndColumn; + bool HasEndLoc = false; + if (!RangeSplit.second.empty()) { + std::pair Split = RangeSplit.second.rsplit(':'); + if (Split.first.getAsInteger(10, EndLine) || + Split.second.getAsInteger(10, EndColumn)) { + // The string does not end in end_line:end_column, so the '-' + // probably belongs to the filename which menas the whole + // string should be parsed. + RangeSplit.first = Str; + } else + HasEndLoc = true; + } + auto Begin = ParsedSourceLocation::FromString(RangeSplit.first); + if (Begin.FileName.empty()) + return None; + if (!HasEndLoc) { + EndLine = Begin.Line; + EndColumn = Begin.Column; + } + return ParsedSourceRange{std::move(Begin.FileName), + {Begin.Line, Begin.Column}, + {EndLine, EndColumn}}; + } +}; } namespace llvm { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/MacroArgs.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/MacroArgs.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/MacroArgs.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/MacroArgs.h 2017-10-17 14:41:54.000000000 +0000 @@ -112,6 +112,20 @@ /// argument, this returns false. bool isVarargsElidedUse() const { return VarargsElided; } + /// Returns true if the macro was defined with a variadic (ellipsis) parameter + /// AND was invoked with at least one token supplied as a variadic argument. + /// + /// \code + /// #define F(a) a + /// #define V(a, ...) __VA_OPT__(a) + /// F() <-- returns false on this invocation. + /// V(,a) <-- returns true on this invocation. + /// V(,) <-- returns false on this invocation. + /// \endcode + /// + + bool invokedWithVariadicArgument(const MacroInfo *const MI) const; + /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of /// tokens into the literal string token that should be produced by the C # /// preprocessor operator. If Charify is true, then it should be turned into diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/Preprocessor.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/Preprocessor.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/Preprocessor.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/Preprocessor.h 2017-10-17 14:41:54.000000000 +0000 @@ -97,6 +97,7 @@ /// token expansion, etc. class Preprocessor { friend class VariadicMacroScopeGuard; + friend class VAOptDefinitionContext; std::shared_ptr PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; @@ -131,6 +132,7 @@ IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma IdentifierInfo *Ident__identifier; // __identifier IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ + IdentifierInfo *Ident__VA_OPT__; // __VA_OPT__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/PreprocessorLexer.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/PreprocessorLexer.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/PreprocessorLexer.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/PreprocessorLexer.h 2017-10-17 14:41:54.000000000 +0000 @@ -77,7 +77,7 @@ PreprocessorLexer(Preprocessor *pp, FileID fid); PreprocessorLexer() - : PP(nullptr), InitialNumSLocEntries(0), + : PP(nullptr), FID(), InitialNumSLocEntries(0), ParsingPreprocessorDirective(false), ParsingFilename(false), LexingRawMode(false) {} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/TokenLexer.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/TokenLexer.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/TokenLexer.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/TokenLexer.h 2017-10-17 14:41:54.000000000 +0000 @@ -15,12 +15,14 @@ #define LLVM_CLANG_LEX_TOKENLEXER_H #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" namespace clang { class MacroInfo; class Preprocessor; class Token; class MacroArgs; + class VAOptExpansionContext; /// TokenLexer - This implements a lexer that returns tokens from a macro body /// or token stream instead of lexing from a character buffer. This is used for @@ -188,7 +190,25 @@ /// CurTokenIdx data members. bool pasteTokens(Token &Tok); - + + /// Takes the tail sequence of tokens within ReplacementToks that represent + /// the just expanded __VA_OPT__ tokens (possibly zero tokens) and transforms + /// them into a string. \p VCtx is used to determine which token represents + /// the first __VA_OPT__ replacement token. + /// + /// \param[in,out] ReplacementToks - Contains the current Replacement Tokens + /// (prior to rescanning and token pasting), the tail end of which represents + /// the tokens just expanded through __VA_OPT__ processing. These (sub) + /// sequence of tokens are folded into one stringified token. + /// + /// \param[in] VCtx - contains relevent contextual information about the + /// state of the tokens around and including the __VA_OPT__ token, necessary + /// for stringification. + + void stringifyVAOPTContents(SmallVectorImpl &ReplacementToks, + const VAOptExpansionContext &VCtx, + SourceLocation VAOPTClosingParenLoc); + /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. void ExpandFunctionArguments(); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/VariadicMacroSupport.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/VariadicMacroSupport.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Lex/VariadicMacroSupport.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Lex/VariadicMacroSupport.h 2017-10-17 14:41:54.000000000 +0000 @@ -1,4 +1,4 @@ -//===- VariadicMacroSupport.h - scope-guards etc. -*- C++ -*---------------===// +//===- VariadicMacroSupport.h - state machines and scope guards -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,40 +17,210 @@ #define LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallVector.h" namespace clang { + class Preprocessor; -/// An RAII class that tracks when the Preprocessor starts and stops lexing the -/// definition of a (ISO C/C++) variadic macro. As an example, this is useful -/// for unpoisoning and repoisoning certain identifiers (such as __VA_ARGS__) -/// that are only allowed in this context. Also, being a friend of the -/// Preprocessor class allows it to access PP's cached identifiers directly (as -/// opposed to performing a lookup each time). -class VariadicMacroScopeGuard { - const Preprocessor &PP; - IdentifierInfo &Ident__VA_ARGS__; - -public: - VariadicMacroScopeGuard(const Preprocessor &P) - : PP(P), Ident__VA_ARGS__(*PP.Ident__VA_ARGS__) { - assert(Ident__VA_ARGS__.isPoisoned() && "__VA_ARGS__ should be poisoned " - "outside an ISO C/C++ variadic " - "macro definition!"); - } - - /// Client code should call this function just before the Preprocessor is - /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro. - void enterScope() { Ident__VA_ARGS__.setIsPoisoned(false); } - - /// Client code should call this function as soon as the Preprocessor has - /// either completed lexing the macro's definition tokens, or an error occured - /// and the context is being exited. This function is idempotent (might be - /// explicitly called, and then reinvoked via the destructor). - void exitScope() { Ident__VA_ARGS__.setIsPoisoned(true); } - - ~VariadicMacroScopeGuard() { exitScope(); } -}; - + /// An RAII class that tracks when the Preprocessor starts and stops lexing + /// the definition of a (ISO C/C++) variadic macro. As an example, this is + /// useful for unpoisoning and repoisoning certain identifiers (such as + /// __VA_ARGS__) that are only allowed in this context. Also, being a friend + /// of the Preprocessor class allows it to access PP's cached identifiers + /// directly (as opposed to performing a lookup each time). + class VariadicMacroScopeGuard { + const Preprocessor &PP; + IdentifierInfo *const Ident__VA_ARGS__; + IdentifierInfo *const Ident__VA_OPT__; + + public: + VariadicMacroScopeGuard(const Preprocessor &P) + : PP(P), Ident__VA_ARGS__(PP.Ident__VA_ARGS__), + Ident__VA_OPT__(PP.Ident__VA_OPT__) { + assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned " + "outside an ISO C/C++ variadic " + "macro definition!"); + assert( + !Ident__VA_OPT__ || + (Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!")); + } + + /// Client code should call this function just before the Preprocessor is + /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro. + void enterScope() { + Ident__VA_ARGS__->setIsPoisoned(false); + if (Ident__VA_OPT__) + Ident__VA_OPT__->setIsPoisoned(false); + } + + /// Client code should call this function as soon as the Preprocessor has + /// either completed lexing the macro's definition tokens, or an error + /// occured and the context is being exited. This function is idempotent + /// (might be explicitly called, and then reinvoked via the destructor). + void exitScope() { + Ident__VA_ARGS__->setIsPoisoned(true); + if (Ident__VA_OPT__) + Ident__VA_OPT__->setIsPoisoned(true); + } + + ~VariadicMacroScopeGuard() { exitScope(); } + }; + + /// \brief A class for tracking whether we're inside a VA_OPT during a + /// traversal of the tokens of a variadic macro definition. + class VAOptDefinitionContext { + /// Contains all the locations of so far unmatched lparens. + SmallVector UnmatchedOpeningParens; + + const IdentifierInfo *const Ident__VA_OPT__; + + + public: + VAOptDefinitionContext(Preprocessor &PP) + : Ident__VA_OPT__(PP.Ident__VA_OPT__) {} + + bool isVAOptToken(const Token &T) const { + return Ident__VA_OPT__ && T.getIdentifierInfo() == Ident__VA_OPT__; + } + + /// Returns true if we have seen the __VA_OPT__ and '(' but before having + /// seen the matching ')'. + bool isInVAOpt() const { return UnmatchedOpeningParens.size(); } + + /// Call this function as soon as you see __VA_OPT__ and '('. + void sawVAOptFollowedByOpeningParens(const SourceLocation LParenLoc) { + assert(!isInVAOpt() && "Must NOT be within VAOPT context to call this"); + UnmatchedOpeningParens.push_back(LParenLoc); + + } + + SourceLocation getUnmatchedOpeningParenLoc() const { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + return UnmatchedOpeningParens.back(); + } + + /// Call this function each time an rparen is seen. It returns true only if + /// the rparen that was just seen was the eventual (non-nested) closing + /// paren for VAOPT, and ejects us out of the VAOPT context. + bool sawClosingParen() { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + UnmatchedOpeningParens.pop_back(); + return !UnmatchedOpeningParens.size(); + } + + /// Call this function each time an lparen is seen. + void sawOpeningParen(SourceLocation LParenLoc) { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + UnmatchedOpeningParens.push_back(LParenLoc); + } + + }; + + /// \brief A class for tracking whether we're inside a VA_OPT during a + /// traversal of the tokens of a macro during macro expansion. + class VAOptExpansionContext : VAOptDefinitionContext { + + Token SyntheticEOFToken; + + // The (spelling) location of the current __VA_OPT__ in the replacement list + // of the function-like macro being expanded. + SourceLocation VAOptLoc; + + // NumOfTokensPriorToVAOpt : when != -1, contains the index *of* the first + // token of the current VAOPT contents (so we know where to start eager + // token-pasting and stringification) *within* the substituted tokens of + // the function-like macro's new replacement list. + int NumOfTokensPriorToVAOpt = -1; + + unsigned LeadingSpaceForStringifiedToken : 1; + + unsigned StringifyBefore : 1; + unsigned CharifyBefore : 1; + + + bool hasStringifyBefore() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return StringifyBefore; + } + + bool isReset() const { + return NumOfTokensPriorToVAOpt == -1 || + VAOptLoc.isInvalid(); + } + + public: + VAOptExpansionContext(Preprocessor &PP) + : VAOptDefinitionContext(PP), LeadingSpaceForStringifiedToken(false), + StringifyBefore(false), CharifyBefore(false) { + SyntheticEOFToken.startToken(); + SyntheticEOFToken.setKind(tok::eof); + } + + void reset() { + VAOptLoc = SourceLocation(); + NumOfTokensPriorToVAOpt = -1; + LeadingSpaceForStringifiedToken = false; + StringifyBefore = false; + CharifyBefore = false; + } + + const Token &getEOFTok() const { return SyntheticEOFToken; } + + void sawHashOrHashAtBefore(const bool HasLeadingSpace, + const bool IsHashAt) { + + StringifyBefore = !IsHashAt; + CharifyBefore = IsHashAt; + LeadingSpaceForStringifiedToken = HasLeadingSpace; + } + + + + bool hasCharifyBefore() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return CharifyBefore; + } + bool hasStringifyOrCharifyBefore() const { + return hasStringifyBefore() || hasCharifyBefore(); + } + + unsigned int getNumberOfTokensPriorToVAOpt() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return NumOfTokensPriorToVAOpt; + } + + bool getLeadingSpaceForStringifiedToken() const { + assert(hasStringifyBefore() && + "Must only be called if this has been marked for stringification"); + return LeadingSpaceForStringifiedToken; + } + + void sawVAOptFollowedByOpeningParens(const SourceLocation VAOptLoc, + const unsigned int NumPriorTokens) { + assert(VAOptLoc.isFileID() && "Must not come from a macro expansion"); + assert(isReset() && "Must only be called if the state has been reset"); + VAOptDefinitionContext::sawVAOptFollowedByOpeningParens(SourceLocation()); + this->VAOptLoc = VAOptLoc; + NumOfTokensPriorToVAOpt = NumPriorTokens; + assert(NumOfTokensPriorToVAOpt > -1 && + "Too many prior tokens"); + } + + SourceLocation getVAOptLoc() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + assert(VAOptLoc.isValid() && "__VA_OPT__ location must be valid"); + return VAOptLoc; + } + using VAOptDefinitionContext::isVAOptToken; + using VAOptDefinitionContext::isInVAOpt; + using VAOptDefinitionContext::sawClosingParen; + using VAOptDefinitionContext::sawOpeningParen; + + }; } // end namespace clang #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/module.modulemap llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/module.modulemap --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/module.modulemap 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/module.modulemap 2017-10-17 14:41:54.000000000 +0000 @@ -71,6 +71,7 @@ module Parse { header "Parse/ParseDiagnostic.h" export * } module Sema { header "Sema/SemaDiagnostic.h" export * } module Serialization { header "Serialization/SerializationDiagnostic.h" export * } + module Refactoring { header "Tooling/Refactoring/RefactoringDiagnostic.h" export * } } module Clang_Driver { @@ -89,7 +90,6 @@ requires cplusplus umbrella "Frontend" - textual header "Frontend/CodeGenOptions.def" textual header "Frontend/LangStandards.def" module * { export * } @@ -98,6 +98,14 @@ exclude header "Frontend/PCHContainerOperations.h" } +// Used in clangBasic +module Clang_Frontend_CodeGenOptions { + requires cplusplus + header "Frontend/CodeGenOptions.h" + textual header "Frontend/CodeGenOptions.def" + export * +} + module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } } module Clang_Index { requires cplusplus umbrella "Index" module * { export * } } module Clang_Lex { requires cplusplus umbrella "Lex" module * { export * } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Parse/Parser.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Parse/Parser.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Parse/Parser.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Parse/Parser.h 2017-10-17 14:41:54.000000000 +0000 @@ -2163,18 +2163,25 @@ private: void ParseBlockId(SourceLocation CaretLoc); - // Check for the start of a C++11 attribute-specifier-seq in a context where - // an attribute is not allowed. + /// Are [[]] attributes enabled? + bool standardAttributesAllowed() const { + const LangOptions &LO = getLangOpts(); + return LO.DoubleSquareBracketAttributes; + } + + // Check for the start of an attribute-specifier-seq in a context where an + // attribute is not allowed. bool CheckProhibitedCXX11Attribute() { assert(Tok.is(tok::l_square)); - if (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_square)) + if (!standardAttributesAllowed() || NextToken().isNot(tok::l_square)) return false; return DiagnoseProhibitedCXX11Attribute(); } + bool DiagnoseProhibitedCXX11Attribute(); void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, SourceLocation CorrectLocation) { - if (!getLangOpts().CPlusPlus11) + if (!standardAttributesAllowed()) return; if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) && Tok.isNot(tok::kw_alignas)) @@ -2194,17 +2201,18 @@ } void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs); - // Forbid C++11 attributes that appear on certain syntactic - // locations which standard permits but we don't supported yet, - // for example, attributes appertain to decl specifiers. + // Forbid C++11 and C2x attributes that appear on certain syntactic locations + // which standard permits but we don't supported yet, for example, attributes + // appertain to decl specifiers. void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID); - /// \brief Skip C++11 attributes and return the end location of the last one. + /// \brief Skip C++11 and C2x attributes and return the end location of the + /// last one. /// \returns SourceLocation() if there are no attributes. SourceLocation SkipCXX11Attributes(); - /// \brief Diagnose and skip C++11 attributes that appear in syntactic + /// \brief Diagnose and skip C++11 and C2x attributes that appear in syntactic /// locations where attributes are not allowed. void DiagnoseAndSkipCXX11Attributes(); @@ -2254,7 +2262,7 @@ AttributeList::Syntax Syntax); void MaybeParseCXX11Attributes(Declarator &D) { - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; ParseCXX11Attributes(attrs, &endLoc); @@ -2263,7 +2271,7 @@ } void MaybeParseCXX11Attributes(ParsedAttributes &attrs, SourceLocation *endLoc = nullptr) { - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX11Attributes(attrsWithRange, endLoc); attrs.takeAllFrom(attrsWithRange); @@ -2272,8 +2280,8 @@ void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *endLoc = nullptr, bool OuterMightBeMessageSend = false) { - if (getLangOpts().CPlusPlus11 && - isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) + if (standardAttributesAllowed() && + isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) ParseCXX11Attributes(attrs, endLoc); } @@ -2281,8 +2289,8 @@ SourceLocation *EndLoc = nullptr); void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *EndLoc = nullptr); - /// \brief Parses a C++-style attribute argument list. Returns true if this - /// results in adding an attribute to the ParsedAttributes list. + /// \brief Parses a C++11 (or C2x)-style attribute argument list. Returns true + /// if this results in adding an attribute to the ParsedAttributes list. bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Sema/AttributeList.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Sema/AttributeList.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Sema/AttributeList.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Sema/AttributeList.h 2017-10-17 14:41:54.000000000 +0000 @@ -100,6 +100,8 @@ AS_GNU, /// [[...]] AS_CXX11, + /// [[...]] + AS_C2x, /// __declspec(...) AS_Declspec, /// [uuid("...")] class Foo @@ -378,6 +380,9 @@ bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); } + bool isC2xAttribute() const { + return SyntaxUsed == AS_C2x; + } bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Sema/Lookup.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Sema/Lookup.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Sema/Lookup.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Sema/Lookup.h 2017-10-17 14:41:54.000000000 +0000 @@ -139,6 +139,7 @@ LookupKind(LookupKind), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), + ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration), AllowHidden(false), @@ -161,6 +162,7 @@ LookupKind(LookupKind), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), + ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration), AllowHidden(false), @@ -181,6 +183,7 @@ LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl), + ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags), Diagnose(false), AllowHidden(Other.AllowHidden), @@ -201,7 +204,9 @@ SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)), NameContextRange(std::move(Other.NameContextRange)), LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)), - Redecl(std::move(Other.Redecl)), HideTags(std::move(Other.HideTags)), + Redecl(std::move(Other.Redecl)), + ExternalRedecl(std::move(Other.ExternalRedecl)), + HideTags(std::move(Other.HideTags)), Diagnose(std::move(Other.Diagnose)), AllowHidden(std::move(Other.AllowHidden)), Shadowed(std::move(Other.Shadowed)) { @@ -221,6 +226,7 @@ LookupKind = std::move(Other.LookupKind); IDNS = std::move(Other.IDNS); Redecl = std::move(Other.Redecl); + ExternalRedecl = std::move(Other.ExternalRedecl); HideTags = std::move(Other.HideTags); Diagnose = std::move(Other.Diagnose); AllowHidden = std::move(Other.AllowHidden); @@ -265,6 +271,17 @@ return Redecl; } + /// True if this lookup is just looking for an existing declaration to link + /// against a declaration with external linkage. + bool isForExternalRedeclaration() const { + return ExternalRedecl; + } + + Sema::RedeclarationKind redeclarationKind() const { + return ExternalRedecl ? Sema::ForExternalRedeclaration : + Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration; + } + /// \brief Specify whether hidden declarations are visible, e.g., /// for recovery reasons. void setAllowHidden(bool AH) { @@ -275,7 +292,7 @@ /// declarations, such as those in modules that have not yet been imported. bool isHiddenDeclarationVisible(NamedDecl *ND) const { return AllowHidden || - (isForRedeclaration() && ND->hasExternalFormalLinkage()); + (isForExternalRedeclaration() && ND->isExternallyDeclarable()); } /// Sets whether tag declarations should be hidden by non-tag @@ -556,7 +573,8 @@ /// \brief Change this lookup's redeclaration kind. void setRedeclarationKind(Sema::RedeclarationKind RK) { - Redecl = RK; + Redecl = (RK != Sema::NotForRedeclaration); + ExternalRedecl = (RK == Sema::ForExternalRedeclaration); configure(); } @@ -719,6 +737,7 @@ unsigned IDNS; // set by configure() bool Redecl; + bool ExternalRedecl; /// \brief True if tag declarations should be hidden if non-tags /// are present diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Sema/Sema.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Sema/Sema.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Sema/Sema.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Sema/Sema.h 2017-10-17 14:41:54.000000000 +0000 @@ -285,15 +285,21 @@ bool isVisibleSlow(const NamedDecl *D); + /// Determine whether two declarations should be linked together, given that + /// the old declaration might not be visible and the new declaration might + /// not have external linkage. bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old, const NamedDecl *New) { - // We are about to link these. It is now safe to compute the linkage of - // the new decl. If the new decl has external linkage, we will - // link it with the hidden decl (which also has external linkage) and - // it will keep having external linkage. If it has internal linkage, we - // will not link it. Since it has no previous decls, it will remain - // with internal linkage. - return isVisible(Old) || New->isExternallyVisible(); + if (isVisible(Old)) + return true; + // See comment in below overload for why it's safe to compute the linkage + // of the new declaration here. + if (New->isExternallyDeclarable()) { + assert(Old->isExternallyDeclarable() && + "should not have found a non-externally-declarable previous decl"); + return true; + } + return false; } bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New); @@ -1527,7 +1533,8 @@ TypeDiagnoser *Diagnoser); struct ModuleScope { - clang::Module *Module; + clang::Module *Module = nullptr; + bool ModuleInterface = false; VisibleModuleSet OuterVisibleModules; }; /// The modules we're currently parsing. @@ -2045,9 +2052,9 @@ SourceLocation SemiLoc); enum class ModuleDeclKind { - Module, ///< 'module X;' + Interface, ///< 'export module X;' + Implementation, ///< 'module X;' Partition, ///< 'module partition X;' - Implementation, ///< 'module implementation X;' }; /// The parser has processed a module-declaration that begins the definition @@ -2914,12 +2921,13 @@ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *input); + Expr *input, bool RequiresADL = true); ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS); + Expr *LHS, Expr *RHS, + bool RequiresADL = true); ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, SourceLocation RLoc, @@ -3034,9 +3042,24 @@ /// purpose of redeclaring the name. NotForRedeclaration = 0, /// \brief The lookup results will be used for redeclaration of a name, - /// if an entity by that name already exists. - ForRedeclaration - }; + /// if an entity by that name already exists and is visible. + ForVisibleRedeclaration, + /// \brief The lookup results will be used for redeclaration of a name + /// with external linkage; non-visible lookup results with external linkage + /// may also be found. + ForExternalRedeclaration + }; + + RedeclarationKind forRedeclarationInCurContext() { + // A declaration with an owning module for linkage can never link against + // anything that is not visible. We don't need to check linkage here; if + // the context has internal linkage, redeclaration lookup won't find things + // from other TUs, and we can't safely compute linkage yet in general. + if (cast(CurContext) + ->getOwningModuleForLinkage(/*IgnoreLinkage*/true)) + return ForVisibleRedeclaration; + return ForExternalRedeclaration; + } /// \brief The possible outcomes of name lookup for a literal operator. enum LiteralOperatorLookupResult { @@ -3265,6 +3288,8 @@ void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace); + bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old); + void DiagnoseAmbiguousLookup(LookupResult &Result); //@} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Serialization/ASTWriter.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Serialization/ASTWriter.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Serialization/ASTWriter.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Serialization/ASTWriter.h 2017-10-17 14:41:54.000000000 +0000 @@ -698,7 +698,8 @@ void ResolvedExceptionSpec(const FunctionDecl *FD) override; void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) override; + const FunctionDecl *Delete, + Expr *ThisArg) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; void StaticDataMemberInstantiated(const VarDecl *D) override; void DefaultArgumentInstantiated(const ParmVarDecl *D) override; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 2017-10-17 14:41:54.000000000 +0000 @@ -132,6 +132,10 @@ HelpText<"Generate dynamic type information">, DescFile<"DynamicTypePropagation.cpp">; +def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">, + HelpText<"Assume that const string-like globals are non-null">, + DescFile<"NonilStringConstantsChecker.cpp">; + } // end "core" let ParentPackage = CoreAlpha in { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h 2017-10-17 14:41:54.000000000 +0000 @@ -196,6 +196,13 @@ return getState()->getSVal(S, getLocationContext()); } + /// \brief Returns true if the value of \p E is greater than or equal to \p + /// Val under unsigned comparison + bool isGreaterOrEqual(const Expr *E, unsigned long long Val); + + /// Returns true if the value of \p E is negative. + bool isNegative(const Expr *E); + /// \brief Generates a new transition in the program state graph /// (ExplodedGraph). Uses the default CheckerContext predecessor node. /// diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h 2017-10-17 14:41:54.000000000 +0000 @@ -16,6 +16,7 @@ namespace clang { namespace tooling { +class RefactoringOptionVisitor; class RefactoringResultConsumer; class RefactoringRuleContext; @@ -43,6 +44,14 @@ /// Returns true when the rule has a source selection requirement that has /// to be fullfilled before refactoring can be performed. virtual bool hasSelectionRequirement() = 0; + + /// Traverses each refactoring option used by the rule and invokes the + /// \c visit callback in the consumer for each option. + /// + /// Options are visited in the order of use, e.g. if a rule has two + /// requirements that use options, the options from the first requirement + /// are visited before the options in the second requirement. + virtual void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) = 0; }; } // end namespace tooling diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h 2017-10-17 14:41:54.000000000 +0000 @@ -11,6 +11,8 @@ #define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H #include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" +#include "clang/Tooling/Refactoring/RefactoringOption.h" #include "clang/Tooling/Refactoring/RefactoringRuleContext.h" #include "llvm/Support/Error.h" #include @@ -46,13 +48,49 @@ Expected evaluate(RefactoringRuleContext &Context) const { if (Context.getSelectionRange().isValid()) return Context.getSelectionRange(); - // FIXME: Use a diagnostic. - return llvm::make_error( - "refactoring action can't be initiated without a selection", - llvm::inconvertibleErrorCode()); + return Context.createDiagnosticError(diag::err_refactor_no_selection); } }; +/// A base class for any requirement that requires some refactoring options. +class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement { +public: + virtual ~RefactoringOptionsRequirement() {} + + /// Returns the set of refactoring options that are used when evaluating this + /// requirement. + virtual ArrayRef> + getRefactoringOptions() const = 0; +}; + +/// A requirement that evaluates to the value of the given \c OptionType when +/// the \c OptionType is a required option. When the \c OptionType is an +/// optional option, the requirement will evaluate to \c None if the option is +/// not specified or to an appropriate value otherwise. +template +class OptionRequirement : public RefactoringOptionsRequirement { +public: + OptionRequirement() : Opt(createRefactoringOption()) {} + + ArrayRef> + getRefactoringOptions() const final override { + return Opt; + } + + Expected + evaluate(RefactoringRuleContext &) const { + return static_cast(Opt.get())->getValue(); + } + +private: + /// The partially-owned option. + /// + /// The ownership of the option is shared among the different requirements + /// because the same option can be used by multiple rules in one refactoring + /// action. + std::shared_ptr Opt; +}; + } // end namespace tooling } // end namespace clang diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h 2017-10-17 14:41:54.000000000 +0000 @@ -24,12 +24,23 @@ inline llvm::Error findError() { return llvm::Error::success(); } +inline void ignoreError() {} + +template +void ignoreError(Expected &First, Expected &... Rest) { + if (!First) + llvm::consumeError(First.takeError()); + ignoreError(Rest...); +} + /// Scans the tuple and returns a valid \c Error if any of the values are /// invalid. template llvm::Error findError(Expected &First, Expected &... Rest) { - if (!First) + if (!First) { + ignoreError(Rest...); return First.takeError(); + } return findError(Rest...); } @@ -49,6 +60,34 @@ RuleType((*std::get(Values))...).invoke(Consumer, Context); } +inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {} + +/// Scans the list of requirements in a rule and visits all the refactoring +/// options that are used by all the requirements. +template +void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor, + const FirstT &First, const RestT &... Rest) { + struct OptionGatherer { + RefactoringOptionVisitor &Visitor; + + void operator()(const RefactoringOptionsRequirement &Requirement) { + for (const auto &Option : Requirement.getRefactoringOptions()) + Option->passToVisitor(Visitor); + } + void operator()(const RefactoringActionRuleRequirement &) {} + }; + (OptionGatherer{Visitor})(First); + return visitRefactoringOptionsImpl(Visitor, Rest...); +} + +template +void visitRefactoringOptions( + RefactoringOptionVisitor &Visitor, + const std::tuple &Requirements, + llvm::index_sequence) { + visitRefactoringOptionsImpl(Visitor, std::get(Requirements)...); +} + /// A type trait that returns true when the given type list has at least one /// type whose base is the given base type. template @@ -97,6 +136,12 @@ RequirementTypes...>::value; } + void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override { + internal::visitRefactoringOptions( + Visitor, Requirements, + llvm::index_sequence_for()); + } + private: std::tuple Requirements; }; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h 2017-10-17 14:41:54.000000000 +0000 @@ -0,0 +1,30 @@ +//===--- RefactoringDiagnostic.h - ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/PartialDiagnostic.h" + +namespace clang { +namespace diag { +enum { +#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY) \ + ENUM, +#define REFACTORINGSTART +#include "clang/Basic/DiagnosticRefactoringKinds.inc" +#undef DIAG + NUM_BUILTIN_REFACTORING_DIAGNOSTICS +}; +} // end namespace diag +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringOption.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringOption.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringOption.h 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringOption.h 2017-10-17 14:41:54.000000000 +0000 @@ -0,0 +1,64 @@ +//===--- RefactoringOption.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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H + +#include "clang/Basic/LLVM.h" +#include +#include + +namespace clang { +namespace tooling { + +class RefactoringOptionVisitor; + +/// A refactoring option is an interface that describes a value that +/// has an impact on the outcome of a refactoring. +/// +/// Refactoring options can be specified using command-line arguments when +/// the clang-refactor tool is used. +class RefactoringOption { +public: + virtual ~RefactoringOption() {} + + /// Returns the name of the refactoring option. + /// + /// Each refactoring option must have a unique name. + virtual StringRef getName() const = 0; + + virtual StringRef getDescription() const = 0; + + /// True when this option must be specified before invoking the refactoring + /// action. + virtual bool isRequired() const = 0; + + /// Invokes the \c visit method in the option consumer that's appropriate + /// for the option's value type. + /// + /// For example, if the option stores a string value, this method will + /// invoke the \c visit method with a reference to an std::string value. + virtual void passToVisitor(RefactoringOptionVisitor &Visitor) = 0; +}; + +/// Constructs a refactoring option of the given type. +/// +/// The ownership of options is shared among requirements that use it because +/// one option can be used by multiple rules in a refactoring action. +template +std::shared_ptr createRefactoringOption() { + static_assert(std::is_base_of::value, + "invalid option type"); + return std::make_shared(); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h 2017-10-17 14:41:54.000000000 +0000 @@ -0,0 +1,58 @@ +//===--- RefactoringOptions.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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h" +#include "clang/Tooling/Refactoring/RefactoringOption.h" +#include "clang/Tooling/Refactoring/RefactoringOptionVisitor.h" +#include "llvm/Support/Error.h" +#include + +namespace clang { +namespace tooling { + +/// A refactoring option that stores a value of type \c T. +template ::value>::type> +class OptionalRefactoringOption : public RefactoringOption { +public: + void passToVisitor(RefactoringOptionVisitor &Visitor) final override { + Visitor.visit(*this, Value); + } + + bool isRequired() const override { return false; } + + using ValueType = Optional; + + const ValueType &getValue() const { return Value; } + +protected: + Optional Value; +}; + +/// A required refactoring option that stores a value of type \c T. +template ::value>::type> +class RequiredRefactoringOption : public OptionalRefactoringOption { +public: + using ValueType = T; + + const ValueType &getValue() const { + return *OptionalRefactoringOption::Value; + } + bool isRequired() const final override { return true; } +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h 2017-10-17 14:41:54.000000000 +0000 @@ -0,0 +1,62 @@ +//===--- RefactoringOptionVisitor.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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H + +#include "clang/Basic/LLVM.h" +#include + +namespace clang { +namespace tooling { + +class RefactoringOption; + +/// An interface that declares functions that handle different refactoring +/// option types. +/// +/// A valid refactoring option type must have a corresponding \c visit +/// declaration in this interface. +class RefactoringOptionVisitor { +public: + virtual ~RefactoringOptionVisitor() {} + + virtual void visit(const RefactoringOption &Opt, + Optional &Value) = 0; +}; + +namespace traits { +namespace internal { + +template struct HasHandle { +private: + template + static auto check(ClassT *) -> typename std::is_same< + decltype(std::declval().visit( + std::declval(), *std::declval *>())), + void>::type; + + template static std::false_type check(...); + +public: + using Type = decltype(check(nullptr)); +}; + +} // end namespace internal + +/// A type trait that returns true iff the given type is a type that can be +/// stored in a refactoring option. +template +struct IsValidOptionType : internal::HasHandle::Type {}; + +} // end namespace traits +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h 2017-10-17 14:41:54.000000000 +0000 @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H #define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H +#include "clang/Basic/DiagnosticError.h" #include "clang/Basic/SourceManager.h" namespace clang { @@ -50,6 +51,17 @@ void setASTContext(ASTContext &Context) { AST = &Context; } + /// Creates an llvm::Error value that contains a diagnostic. + /// + /// The errors should not outlive the context. + llvm::Error createDiagnosticError(SourceLocation Loc, unsigned DiagID) { + return DiagnosticError::create(Loc, PartialDiagnostic(DiagID, DiagStorage)); + } + + llvm::Error createDiagnosticError(unsigned DiagID) { + return createDiagnosticError(SourceLocation(), DiagID); + } + private: /// The source manager for the translation unit / file on which a refactoring /// action might operate on. @@ -60,6 +72,8 @@ /// An optional AST for the translation unit on which a refactoring action /// might operate on. ASTContext *AST = nullptr; + /// The allocator for diagnostics. + PartialDiagnostic::StorageAllocator DiagStorage; }; } // end namespace tooling diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h 2017-10-17 14:41:54.000000000 +0000 @@ -17,6 +17,7 @@ #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/RefactoringOptions.h" #include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" #include "llvm/Support/Error.h" @@ -45,12 +46,19 @@ bool PrintLocations; }; +class NewNameOption : public RequiredRefactoringOption { +public: + StringRef getName() const override { return "new-name"; } + StringRef getDescription() const override { + return "The new name to change the symbol to"; + } +}; + /// Returns source replacements that correspond to the rename of the given /// symbol occurrences. llvm::Expected> createRenameReplacements(const SymbolOccurrences &Occurrences, - const SourceManager &SM, - ArrayRef NewNameStrings); + const SourceManager &SM, const SymbolName &NewName); /// Rename all symbols identified by the given USRs. class QualifiedRenamingAction { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Analysis/BodyFarm.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Analysis/BodyFarm.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Analysis/BodyFarm.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Analysis/BodyFarm.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -108,7 +108,7 @@ /// Returns a *first* member field of a record declaration with a given name. /// \return an nullptr if no member with such a name exists. - NamedDecl *findMemberField(const CXXRecordDecl *RD, StringRef Name); + ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name); private: ASTContext &C; @@ -234,7 +234,7 @@ OK_Ordinary); } -NamedDecl *ASTMaker::findMemberField(const CXXRecordDecl *RD, StringRef Name) { +ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) { CXXBasePaths Paths( /* FindAmbiguities=*/false, @@ -246,7 +246,7 @@ DeclContextLookupResult Decls = RD->lookup(DeclName); for (NamedDecl *FoundDecl : Decls) if (!FoundDecl->getDeclContext()->isFunctionOrMethod()) - return FoundDecl; + return cast(FoundDecl); return nullptr; } @@ -327,6 +327,34 @@ const ParmVarDecl *Flag = D->getParamDecl(0); const ParmVarDecl *Callback = D->getParamDecl(1); QualType CallbackType = Callback->getType().getNonReferenceType(); + QualType FlagType = Flag->getType().getNonReferenceType(); + auto *FlagRecordDecl = dyn_cast_or_null(FlagType->getAsTagDecl()); + + if (!FlagRecordDecl) { + DEBUG(llvm::dbgs() << "Flag field is not a record: " + << "unknown std::call_once implementation, " + << "ignoring the call.\n"); + return nullptr; + } + + // We initially assume libc++ implementation of call_once, + // where the once_flag struct has a field `__state_`. + ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_"); + + // Otherwise, try libstdc++ implementation, with a field + // `_M_once` + if (!FlagFieldDecl) { + DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, " + << "assuming libstdc++ implementation\n"); + FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once"); + } + + if (!FlagFieldDecl) { + DEBUG(llvm::dbgs() << "No field _M_once found on std::once flag struct: " + << "unknown std::call_once implementation, " + << "ignoring the call"); + return nullptr; + } bool isLambdaCall = CallbackType->getAsCXXRecordDecl() && CallbackType->getAsCXXRecordDecl()->isLambda(); @@ -355,29 +383,13 @@ CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs); } - QualType FlagType = Flag->getType().getNonReferenceType(); DeclRefExpr *FlagDecl = M.makeDeclRefExpr(Flag, /* RefersToEnclosingVariableOrCapture=*/true, /* GetNonReferenceType=*/true); - CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl(); - - // Note: here we are assuming libc++ implementation of call_once, - // which has a struct with a field `__state_`. - // Body farming might not work for other `call_once` implementations. - NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_"); - ValueDecl *FieldDecl; - if (FoundDecl) { - FieldDecl = dyn_cast(FoundDecl); - } else { - DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, " - << "unable to synthesize call_once body, ignoring " - << "the call.\n"); - return nullptr; - } - MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FieldDecl); + MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl); assert(Deref->isLValue()); QualType DerefType = Deref->getType(); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ASTContext.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ASTContext.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ASTContext.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ASTContext.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -697,8 +697,8 @@ llvm_unreachable("Invalid CXXABI type!"); } -static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, - const LangOptions &LOpts) { +static const LangASMap *getAddressSpaceMap(const TargetInfo &T, + const LangOptions &LOpts) { if (LOpts.FakeAddressSpaceMap) { // The fake address space map must have a distinct entry for each // language-specific address space. @@ -707,6 +707,7 @@ 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 0, // opencl_private 4, // opencl_generic 5, // cuda_device 6, // cuda_constant @@ -2282,8 +2283,8 @@ return QualType(eq, fastQuals); } -QualType -ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const { +QualType ASTContext::getAddrSpaceQualType(QualType T, + LangAS AddressSpace) const { QualType CanT = getCanonicalType(T); if (CanT.getAddressSpace() == AddressSpace) return T; @@ -5671,7 +5672,6 @@ // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! - SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); CharUnits ParmOffset = PtrSize; for (auto PI : Decl->parameters()) { @@ -5779,7 +5779,6 @@ // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! - SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); // The first two arguments (self and _cmd) are pointers; account for // their size. @@ -8871,8 +8870,8 @@ char *End; unsigned AddrSpace = strtoul(Str, &End, 10); if (End != Str && AddrSpace != 0) { - Type = Context.getAddrSpaceQualType( - Type, AddrSpace + LangAS::FirstTargetAddressSpace); + Type = Context.getAddrSpaceQualType(Type, + getLangASFromTargetAS(AddrSpace)); Str = End; } if (c == '*') @@ -9695,20 +9694,20 @@ } uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { - unsigned AS; + LangAS AS; if (QT->getUnqualifiedDesugaredType()->isNullPtrType()) - AS = 0; + AS = LangAS::Default; else AS = QT->getPointeeType().getAddressSpace(); return getTargetInfo().getNullPointerValue(AS); } -unsigned ASTContext::getTargetAddressSpace(unsigned AS) const { - if (AS >= LangAS::FirstTargetAddressSpace) - return AS - LangAS::FirstTargetAddressSpace; +unsigned ASTContext::getTargetAddressSpace(LangAS AS) const { + if (isTargetAddressSpace(AS)) + return toTargetAddressSpace(AS); else - return (*AddrSpaceMap)[AS]; + return (*AddrSpaceMap)[(unsigned)AS]; } // Explicitly instantiate this in case a Redeclarable is used from a TU that diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/CommentSema.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/CommentSema.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/CommentSema.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/CommentSema.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -813,7 +813,7 @@ } bool Sema::isFunctionOrMethodVariadic() { - if (!isAnyFunctionDecl() && !isObjCMethodDecl() && !isFunctionTemplateDecl()) + if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl) return false; if (const FunctionDecl *FD = dyn_cast(ThisDeclInfo->CurrentDecl)) @@ -824,6 +824,14 @@ if (const ObjCMethodDecl *MD = dyn_cast(ThisDeclInfo->CurrentDecl)) return MD->isVariadic(); + if (const TypedefNameDecl *TD = + dyn_cast(ThisDeclInfo->CurrentDecl)) { + QualType Type = TD->getUnderlyingType(); + if (Type->isFunctionPointerType() || Type->isBlockPointerType()) + Type = Type->getPointeeType(); + if (const auto *FT = Type->getAs()) + return FT->isVariadic(); + } return false; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/DeclBase.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/DeclBase.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/DeclBase.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/DeclBase.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -315,12 +315,11 @@ } bool Decl::isInAnonymousNamespace() const { - const DeclContext *DC = getDeclContext(); - do { + for (const DeclContext *DC = getDeclContext(); DC; DC = DC->getParent()) { if (const NamespaceDecl *ND = dyn_cast(DC)) if (ND->isAnonymousNamespace()) return true; - } while ((DC = DC->getParent())); + } return false; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/Decl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/Decl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/Decl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/Decl.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -515,6 +515,7 @@ } static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { + // FIXME: Handle isModulePrivate. switch (D->getModuleOwnershipKind()) { case Decl::ModuleOwnershipKind::Unowned: case Decl::ModuleOwnershipKind::ModulePrivate: @@ -546,7 +547,8 @@ // declaration has module linkage. if (auto *M = D->getOwningModule()) if (M->Kind == Module::ModuleInterfaceUnit) - if (!isExportedFromModuleIntefaceUnit(D)) + if (!isExportedFromModuleIntefaceUnit( + cast(D->getCanonicalDecl()))) return LinkageInfo(ModuleLinkage, DefaultVisibility, false); return LinkageInfo::external(); @@ -1393,7 +1395,7 @@ : NamedDecl::VisibilityForValue)); } -Module *NamedDecl::getOwningModuleForLinkage() const { +Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { Module *M = getOwningModule(); if (!M) return nullptr; @@ -1411,7 +1413,17 @@ // for linkage purposes. But internal linkage declarations in the global // module fragment of a particular module are owned by that module for // linkage purposes. - return hasExternalFormalLinkage() ? nullptr : M->Parent; + if (IgnoreLinkage) + return nullptr; + bool InternalLinkage; + if (auto *ND = dyn_cast(this)) + InternalLinkage = !ND->hasExternalFormalLinkage(); + else { + auto *NSD = dyn_cast(this); + InternalLinkage = (NSD && NSD->isAnonymousNamespace()) || + isInAnonymousNamespace(); + } + return InternalLinkage ? M->Parent : nullptr; } llvm_unreachable("unknown module kind"); @@ -2720,6 +2732,20 @@ return Params == FPT->getNumParams(); } +bool FunctionDecl::isDestroyingOperatorDelete() const { + // C++ P0722: + // Within a class C, a single object deallocation function with signature + // (T, std::destroying_delete_t, ) + // is a destroying operator delete. + if (!isa(this) || getOverloadedOperator() != OO_Delete || + getNumParams() < 2) + return false; + + auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl(); + return RD && RD->isInStdNamespace() && RD->getIdentifier() && + RD->getIdentifier()->isStr("destroying_delete_t"); +} + LanguageLinkage FunctionDecl::getLanguageLinkage() const { return getDeclLanguageLinkage(*this); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/DeclCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/DeclCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/DeclCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/DeclCXX.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -100,7 +100,7 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - CXXRecordDecl* PrevDecl, + CXXRecordDecl *PrevDecl, bool DelayTypeCreation) { CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl); @@ -1788,6 +1788,14 @@ return true; unsigned UsualParams = 1; + // C++ P0722: + // A destroying operator delete is a usual deallocation function if + // removing the std::destroying_delete_t parameter and changing the + // first parameter type from T* to void* results in the signature of + // a usual deallocation function. + if (isDestroyingOperatorDelete()) + ++UsualParams; + // C++ <=14 [basic.stc.dynamic.deallocation]p2: // [...] If class T does not declare such an operator delete but does // declare a member deallocation function named operator delete with @@ -2187,12 +2195,13 @@ isInline, isImplicitlyDeclared); } -void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) { +void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { auto *First = cast(getFirstDecl()); if (OD && !First->OperatorDelete) { First->OperatorDelete = OD; + First->OperatorDeleteThisArg = ThisArg; if (auto *L = getASTMutationListener()) - L->ResolvedOperatorDelete(First, OD); + L->ResolvedOperatorDelete(First, OD, ThisArg); } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ExprConstant.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ExprConstant.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ExprConstant.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ExprConstant.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -573,6 +573,31 @@ /// declaration whose initializer is being evaluated, if any. APValue *EvaluatingDeclValue; + /// EvaluatingObject - Pair of the AST node that an lvalue represents and + /// the call index that that lvalue was allocated in. + typedef std::pair EvaluatingObject; + + /// EvaluatingConstructors - Set of objects that are currently being + /// constructed. + llvm::DenseSet EvaluatingConstructors; + + struct EvaluatingConstructorRAII { + EvalInfo &EI; + EvaluatingObject Object; + bool DidInsert; + EvaluatingConstructorRAII(EvalInfo &EI, EvaluatingObject Object) + : EI(EI), Object(Object) { + DidInsert = EI.EvaluatingConstructors.insert(Object).second; + } + ~EvaluatingConstructorRAII() { + if (DidInsert) EI.EvaluatingConstructors.erase(Object); + } + }; + + bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex) { + return EvaluatingConstructors.count(EvaluatingObject(Decl, CallIndex)); + } + /// The current array initialization index, if we're performing array /// initialization. uint64_t ArrayInitIndex = -1; @@ -666,6 +691,7 @@ void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; EvaluatingDeclValue = &Value; + EvaluatingConstructors.insert({Base, 0}); } const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } @@ -3098,10 +3124,9 @@ } // During the construction of an object, it is not yet 'const'. - // FIXME: We don't set up EvaluatingDecl for local variables or temporaries, - // and this doesn't do quite the right thing for const subobjects of the + // FIXME: This doesn't do quite the right thing for const subobjects of the // object under construction. - if (LVal.getLValueBase() == Info.EvaluatingDecl) { + if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) { BaseType = Info.Ctx.getCanonicalType(BaseType); BaseType.removeLocalConst(); } @@ -4254,6 +4279,8 @@ return false; } + EvalInfo::EvaluatingConstructorRAII EvalObj( + Info, {This.getLValueBase(), This.CallIndex}); CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); // FIXME: Creating an APValue just to hold a nonexistent return value is @@ -7902,6 +7929,9 @@ return BuiltinOp == Builtin::BI__atomic_always_lock_free ? Success(0, E) : Error(E); } + case Builtin::BIomp_is_initial_device: + // We can decide statically which value the runtime would return if called. + return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/Expr.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/Expr.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/Expr.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/Expr.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -3293,20 +3293,20 @@ // Check that it is a cast to void*. if (const PointerType *PT = CE->getType()->getAs()) { QualType Pointee = PT->getPointeeType(); - Qualifiers Q = Pointee.getQualifiers(); - // In OpenCL v2.0 generic address space acts as a placeholder - // and should be ignored. - bool IsASValid = true; - if (Ctx.getLangOpts().OpenCLVersion >= 200) { - if (Pointee.getAddressSpace() == LangAS::opencl_generic) - Q.removeAddressSpace(); - else - IsASValid = false; - } + // Only (void*)0 or equivalent are treated as nullptr. If pointee type + // has non-default address space it is not treated as nullptr. + // (__generic void*)0 in OpenCL 2.0 should not be treated as nullptr + // since it cannot be assigned to a pointer to constant address space. + bool PointeeHasDefaultAS = + Pointee.getAddressSpace() == LangAS::Default || + (Ctx.getLangOpts().OpenCLVersion >= 200 && + Pointee.getAddressSpace() == LangAS::opencl_generic) || + (Ctx.getLangOpts().OpenCL && + Ctx.getLangOpts().OpenCLVersion < 200 && + Pointee.getAddressSpace() == LangAS::opencl_private); - if (IsASValid && !Q.hasQualifiers() && - Pointee->isVoidType() && // to void* - CE->getSubExpr()->getType()->isIntegerType()) // from int. + if (PointeeHasDefaultAS && Pointee->isVoidType() && // to void* + CE->getSubExpr()->getType()->isIntegerType()) // from int. return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC); } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ExprCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ExprCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ExprCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ExprCXX.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -160,6 +160,22 @@ // CXXDeleteExpr QualType CXXDeleteExpr::getDestroyedType() const { const Expr *Arg = getArgument(); + + // For a destroying operator delete, we may have implicitly converted the + // pointer type to the type of the parameter of the 'operator delete' + // function. + while (auto *ICE = dyn_cast(Arg)) { + if (ICE->getCastKind() == CK_DerivedToBase || + ICE->getCastKind() == CK_UncheckedDerivedToBase || + ICE->getCastKind() == CK_NoOp) { + assert((ICE->getCastKind() == CK_NoOp || + getOperatorDelete()->isDestroyingOperatorDelete()) && + "only a destroying operator delete can have a converted arg"); + Arg = ICE->getSubExpr(); + } else + break; + } + // The type-to-delete may not be a pointer if it's a dependent type. const QualType ArgType = Arg->getType(); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ItaniumMangle.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ItaniumMangle.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/ItaniumMangle.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/ItaniumMangle.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -2222,20 +2222,22 @@ // ::= U SmallString<64> ASString; - unsigned AS = Quals.getAddressSpace(); + LangAS AS = Quals.getAddressSpace(); if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { // ::= "AS" unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); - ASString = "AS" + llvm::utostr(TargetAS); + if (TargetAS != 0) + ASString = "AS" + llvm::utostr(TargetAS); } else { switch (AS) { default: llvm_unreachable("Not a language specific address space"); - // ::= "CL" [ "global" | "local" | "constant | - // "generic" ] + // ::= "CL" [ "global" | "local" | "constant" | + // "private"| "generic" ] case LangAS::opencl_global: ASString = "CLglobal"; break; case LangAS::opencl_local: ASString = "CLlocal"; break; case LangAS::opencl_constant: ASString = "CLconstant"; break; + case LangAS::opencl_private: ASString = "CLprivate"; break; case LangAS::opencl_generic: ASString = "CLgeneric"; break; // ::= "CU" [ "device" | "constant" | "shared" ] case LangAS::cuda_device: ASString = "CUdevice"; break; @@ -2243,7 +2245,8 @@ case LangAS::cuda_shared: ASString = "CUshared"; break; } } - mangleVendorQualifier(ASString); + if (!ASString.empty()) + mangleVendorQualifier(ASString); } // The ARC ownership qualifiers start with underscores. @@ -3625,7 +3628,6 @@ if (const Expr *Base = PDE->getBase()) mangleMemberExprBase(Base, PDE->isArrow()); NestedNameSpecifier *Qualifier = PDE->getQualifier(); - QualType ScopeType; if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) { if (Qualifier) { mangleUnresolvedPrefix(Qualifier, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/RecordLayoutBuilder.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/RecordLayoutBuilder.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/RecordLayoutBuilder.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/RecordLayoutBuilder.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -1169,7 +1169,6 @@ // Query the external layout to see if it provides an offset. bool HasExternalLayout = false; if (UseExternalLayout) { - llvm::DenseMap::iterator Known; if (Base->IsVirtual) HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset); else @@ -1732,7 +1731,7 @@ const ArrayType* ATy = Context.getAsArrayType(D->getType()); FieldAlign = Context.getTypeAlignInChars(ATy->getElementType()); } else if (const ReferenceType *RT = D->getType()->getAs()) { - unsigned AS = RT->getPointeeType().getAddressSpace(); + unsigned AS = Context.getTargetAddressSpace(RT->getPointeeType()); FieldSize = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS)); FieldAlign = diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/StmtProfile.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/StmtProfile.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/StmtProfile.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/StmtProfile.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -1418,7 +1418,7 @@ llvm_unreachable("Invalid overloaded operator expression"); } -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) #if _MSC_VER == 1911 // Work around https://developercommunity.visualstudio.com/content/problem/84002/clang-cl-when-built-with-vc-2017-crashes-cause-vc.html // MSVC 2017 update 3 miscompiles this function, and a clang built with it @@ -1459,7 +1459,7 @@ ID.AddInteger(S->getOperator()); } -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) #if _MSC_VER == 1911 #pragma optimize("", on) #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/TypePrinter.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/TypePrinter.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/AST/TypePrinter.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/AST/TypePrinter.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -1320,7 +1320,9 @@ default: llvm_unreachable("This attribute should have been handled already"); case AttributedType::attr_address_space: OS << "address_space("; - OS << T->getEquivalentType().getAddressSpace(); + // FIXME: printing the raw LangAS value is wrong. This should probably + // use the same code as Qualifiers::print() + OS << (unsigned)T->getEquivalentType().getAddressSpace(); OS << ')'; break; @@ -1645,7 +1647,7 @@ if (getCVRQualifiers()) return false; - if (getAddressSpace()) + if (getAddressSpace() != LangAS::Default) return false; if (getObjCGCAttr()) @@ -1676,17 +1678,21 @@ OS << "__unaligned"; addSpace = true; } - if (unsigned addrspace = getAddressSpace()) { - if (addSpace) - OS << ' '; - addSpace = true; - switch (addrspace) { + LangAS addrspace = getAddressSpace(); + if (addrspace != LangAS::Default) { + if (addrspace != LangAS::opencl_private) { + if (addSpace) + OS << ' '; + addSpace = true; + switch (addrspace) { case LangAS::opencl_global: OS << "__global"; break; case LangAS::opencl_local: OS << "__local"; break; + case LangAS::opencl_private: + break; case LangAS::opencl_constant: case LangAS::cuda_constant: OS << "__constant"; @@ -1701,10 +1707,10 @@ OS << "__shared"; break; default: - assert(addrspace >= LangAS::FirstTargetAddressSpace); OS << "__attribute__((address_space("; - OS << addrspace - LangAS::FirstTargetAddressSpace; + OS << toTargetAddressSpace(addrspace); OS << ")))"; + } } } if (Qualifiers::GC gc = getObjCGCAttr()) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/ASTMatchers/ASTMatchFinder.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/ASTMatchers/ASTMatchFinder.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/ASTMatchers/ASTMatchFinder.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/ASTMatchers/ASTMatchFinder.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -734,7 +734,10 @@ BoundNodesTreeBuilder *Builder) { const Type *const CanonicalType = ActiveASTContext->getCanonicalType(TypeNode); - for (const TypedefNameDecl *Alias : TypeAliases.lookup(CanonicalType)) { + auto Aliases = TypeAliases.find(CanonicalType); + if (Aliases == TypeAliases.end()) + return false; + for (const TypedefNameDecl *Alias : Aliases->second) { BoundNodesTreeBuilder Result(*Builder); if (Matcher.matches(*Alias, this, &Result)) { *Builder = std::move(Result); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Builtins.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Builtins.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Builtins.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Builtins.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -75,8 +75,9 @@ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES) == OCLC20_LANG; bool OclCUnsupported = !LangOpts.OpenCL && (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES); + bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG; return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported && - !OclC1Unsupported && !OclC2Unsupported && + !OclC1Unsupported && !OclC2Unsupported && !OpenMPUnsupported && !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/DiagnosticIDs.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/DiagnosticIDs.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/DiagnosticIDs.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/DiagnosticIDs.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -43,7 +43,7 @@ unsigned SFINAE : 2; unsigned WarnNoWerror : 1; unsigned WarnShowInSystemHeader : 1; - unsigned Category : 5; + unsigned Category : 6; uint16_t OptionGroupIndex; @@ -88,6 +88,7 @@ VALIDATE_DIAG_SIZE(COMMENT) VALIDATE_DIAG_SIZE(SEMA) VALIDATE_DIAG_SIZE(ANALYSIS) +VALIDATE_DIAG_SIZE(REFACTORING) #undef VALIDATE_DIAG_SIZE #undef STRINGIFY_NAME @@ -112,6 +113,7 @@ #include "clang/Basic/DiagnosticCrossTUKinds.inc" #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" +#include "clang/Basic/DiagnosticRefactoringKinds.inc" #undef DIAG }; @@ -150,6 +152,7 @@ CATEGORY(CROSSTU, COMMENT) CATEGORY(SEMA, CROSSTU) CATEGORY(ANALYSIS, SEMA) +CATEGORY(REFACTORING, ANALYSIS) #undef CATEGORY // Avoid out of bounds reads. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/OpenMPKinds.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/OpenMPKinds.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/OpenMPKinds.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/OpenMPKinds.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -890,6 +890,9 @@ CaptureRegions.push_back(OMPD_target); CaptureRegions.push_back(OMPD_teams); break; + case OMPD_teams_distribute: + CaptureRegions.push_back(OMPD_teams); + break; case OMPD_teams: case OMPD_simd: case OMPD_for: @@ -913,7 +916,6 @@ case OMPD_taskloop_simd: case OMPD_distribute_parallel_for_simd: case OMPD_distribute_simd: - case OMPD_teams_distribute: case OMPD_teams_distribute_simd: case OMPD_teams_distribute_parallel_for_simd: case OMPD_teams_distribute_parallel_for: diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/TargetInfo.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/TargetInfo.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/TargetInfo.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/TargetInfo.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -19,10 +19,11 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetParser.h" #include using namespace clang; -static const LangAS::Map DefaultAddrSpaceMap = { 0 }; +static const LangASMap DefaultAddrSpaceMap = {0}; // TargetInfo Constructor. TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { @@ -290,8 +291,15 @@ void TargetInfo::adjust(LangOptions &Opts) { if (Opts.NoBitFieldTypeAlign) UseBitFieldTypeAlignment = false; - if (Opts.ShortWChar) - WCharType = UnsignedShort; + + switch (Opts.WCharSize) { + default: llvm_unreachable("invalid wchar_t width"); + case 0: break; + case 1: WCharType = Opts.WCharIsSigned ? SignedChar : UnsignedChar; break; + case 2: WCharType = Opts.WCharIsSigned ? SignedShort : UnsignedShort; break; + case 4: WCharType = Opts.WCharIsSigned ? SignedInt : UnsignedInt; break; + } + if (Opts.AlignDouble) { DoubleAlign = LongLongAlign = 64; LongDoubleAlign = 64; @@ -348,7 +356,7 @@ return true; } -LangAS::ID TargetInfo::getOpenCLTypeAddrSpace(const Type *T) const { +LangAS TargetInfo::getOpenCLTypeAddrSpace(const Type *T) const { auto BT = dyn_cast(T); if (!BT) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AArch64.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AArch64.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AArch64.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AArch64.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -15,6 +15,7 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" using namespace clang; using namespace clang::targets; @@ -26,6 +27,8 @@ #define BUILTIN(ID, TYPE, ATTRS) \ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, +#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ + {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, #include "clang/Basic/BuiltinsAArch64.def" }; @@ -34,18 +37,19 @@ : TargetInfo(Triple), ABI("aapcs") { if (getTriple().getOS() == llvm::Triple::NetBSD || getTriple().getOS() == llvm::Triple::OpenBSD) { - WCharType = SignedInt; - // NetBSD apparently prefers consistency across ARM targets to // consistency across 64-bit targets. Int64Type = SignedLongLong; IntMaxType = SignedLongLong; } else { - WCharType = UnsignedInt; + if (!getTriple().isOSDarwin()) + WCharType = UnsignedInt; + Int64Type = SignedLong; IntMaxType = SignedLong; } + LongWidth = LongAlign = PointerWidth = PointerAlign = 64; MaxVectorAlign = 128; MaxAtomicInlineWidth = 128; @@ -154,7 +158,8 @@ if (Opts.UnsafeFPMath) Builder.defineMacro("__ARM_FP_FAST", "1"); - Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); + Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", + llvm::utostr(Opts.WCharSize ? Opts.WCharSize : 4)); Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); @@ -420,7 +425,6 @@ // This is an LLP64 platform. // int:4, long:4, long long:8, long double:8. - WCharType = UnsignedShort; IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; DoubleAlign = LongLongAlign = 64; @@ -502,7 +506,6 @@ const TargetOptions &Opts) : DarwinTargetInfo(Triple, Opts) { Int64Type = SignedLongLong; - WCharType = SignedInt; UseSignedCharForObjCBool = false; LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AMDGPU.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AMDGPU.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AMDGPU.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AMDGPU.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -42,44 +42,48 @@ "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"; -static const LangAS::Map AMDGPUPrivIsZeroDefIsGenMap = { +static const LangASMap AMDGPUPrivIsZeroDefIsGenMap = { 4, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 0, // opencl_private 4, // opencl_generic 1, // cuda_device 2, // cuda_constant 3 // cuda_shared }; -static const LangAS::Map AMDGPUGenIsZeroDefIsGenMap = { +static const LangASMap AMDGPUGenIsZeroDefIsGenMap = { 0, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 5, // opencl_private 0, // opencl_generic 1, // cuda_device 2, // cuda_constant 3 // cuda_shared }; -static const LangAS::Map AMDGPUPrivIsZeroDefIsPrivMap = { +static const LangASMap AMDGPUPrivIsZeroDefIsPrivMap = { 0, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 0, // opencl_private 4, // opencl_generic 1, // cuda_device 2, // cuda_constant 3 // cuda_shared }; -static const LangAS::Map AMDGPUGenIsZeroDefIsPrivMap = { +static const LangASMap AMDGPUGenIsZeroDefIsPrivMap = { 5, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 5, // opencl_private 0, // opencl_generic 1, // cuda_device 2, // cuda_constant diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AMDGPU.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AMDGPU.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AMDGPU.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AMDGPU.h 2017-10-17 14:41:54.000000000 +0000 @@ -258,7 +258,7 @@ } } - LangAS::ID getOpenCLTypeAddrSpace(const Type *T) const override { + LangAS getOpenCLTypeAddrSpace(const Type *T) const override { auto BT = dyn_cast(T); if (!BT) @@ -279,8 +279,8 @@ } } - llvm::Optional getConstantAddressSpace() const override { - return LangAS::FirstTargetAddressSpace + AS.Constant; + llvm::Optional getConstantAddressSpace() const override { + return getLangASFromTargetAS(AS.Constant); } /// \returns Target specific vtbl ptr address space. @@ -318,7 +318,7 @@ // In amdgcn target the null pointer in global, constant, and generic // address space has value 0 but in private and local address space has // value ~0. - uint64_t getNullPointerValue(unsigned AS) const override { + uint64_t getNullPointerValue(LangAS AS) const override { return AS == LangAS::opencl_local ? ~0 : 0; } }; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/ARM.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/ARM.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/ARM.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/ARM.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -36,20 +36,10 @@ else SizeType = UnsignedInt; - switch (T.getOS()) { - case llvm::Triple::NetBSD: - case llvm::Triple::OpenBSD: - WCharType = SignedInt; - break; - case llvm::Triple::Win32: - WCharType = UnsignedShort; - break; - case llvm::Triple::Linux: - default: - // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. + bool IsNetBSD = T.getOS() == llvm::Triple::NetBSD; + bool IsOpenBSD = T.getOS() == llvm::Triple::OpenBSD; + if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD) WCharType = UnsignedInt; - break; - } UseBitFieldTypeAlignment = true; @@ -99,7 +89,6 @@ else SizeType = UnsignedLong; - // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. WCharType = SignedInt; // Do not respect the alignment of bit-field types when laying out @@ -689,7 +678,8 @@ "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP)); } - Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); + Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", + llvm::utostr(Opts.WCharSize ? Opts.WCharSize : 4)); Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); @@ -932,7 +922,6 @@ WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : WindowsTargetInfo(Triple, Opts), Triple(Triple) { - WCharType = UnsignedShort; SizeType = UnsignedInt; } @@ -1023,8 +1012,8 @@ CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : ARMleTargetInfo(Triple, Opts) { + this->WCharType = TargetInfo::UnsignedShort; TLSSupported = false; - WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AVR.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AVR.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/AVR.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/AVR.h 2017-10-17 14:41:55.000000000 +0000 @@ -52,7 +52,6 @@ PtrDiffType = SignedInt; IntPtrType = SignedInt; Char16Type = UnsignedInt; - WCharType = SignedInt; WIntType = SignedInt; Char32Type = UnsignedLong; SigAtomicType = SignedChar; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/NVPTX.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/NVPTX.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/NVPTX.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/NVPTX.h 2017-10-17 14:41:55.000000000 +0000 @@ -28,6 +28,7 @@ 1, // opencl_global 3, // opencl_local 4, // opencl_constant + 0, // opencl_private // FIXME: generic has to be added to the target 0, // opencl_generic 1, // cuda_device diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/OSTargets.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/OSTargets.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/OSTargets.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/OSTargets.h 2017-10-17 14:41:55.000000000 +0000 @@ -477,7 +477,7 @@ public: PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : OSTargetInfo(Triple, Opts) { - this->WCharType = this->UnsignedShort; + this->WCharType = TargetInfo::UnsignedShort; // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits). this->MaxTLSAlign = 256; @@ -561,7 +561,6 @@ public: SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : OSTargetInfo(Triple, Opts) { - this->WCharType = this->SignedInt; // FIXME: WIntType should be SignedLong } }; @@ -628,7 +627,9 @@ public: WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : OSTargetInfo(Triple, Opts) {} + : OSTargetInfo(Triple, Opts) { + this->WCharType = TargetInfo::UnsignedShort; + } }; template diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/SPIR.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/SPIR.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/SPIR.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/SPIR.h 2017-10-17 14:41:55.000000000 +0000 @@ -27,6 +27,7 @@ 1, // opencl_global 3, // opencl_local 2, // opencl_constant + 0, // opencl_private 4, // opencl_generic 0, // cuda_device 0, // cuda_constant diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/TCE.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/TCE.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/TCE.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/TCE.h 2017-10-17 14:41:55.000000000 +0000 @@ -35,6 +35,7 @@ 3, // opencl_global 4, // opencl_local 5, // opencl_constant + 0, // opencl_private // FIXME: generic has to be added to the target 0, // opencl_generic 0, // cuda_device diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/X86.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/X86.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/X86.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/X86.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -229,6 +229,8 @@ setFeatureEnabledImpl(Features, "cx16", true); break; + case CK_KNM: + // TODO: Add avx5124fmaps/avx5124vnniw. case CK_KNL: setFeatureEnabledImpl(Features, "avx512f", true); setFeatureEnabledImpl(Features, "avx512cd", true); @@ -853,6 +855,8 @@ case CK_KNL: defineCPUMacros(Builder, "knl"); break; + case CK_KNM: + break; case CK_Lakemont: Builder.defineMacro("__tune_lakemont__"); break; @@ -1293,6 +1297,7 @@ .Case("amd", true) .Case("amdfam10h", true) .Case("amdfam15h", true) + .Case("amdfam17h", true) .Case("atom", true) .Case("barcelona", true) .Case("bdver1", true) @@ -1552,6 +1557,7 @@ .Cases("skylake-avx512", "skx", CK_SkylakeServer) .Case("cannonlake", CK_Cannonlake) .Case("knl", CK_KNL) + .Case("knm", CK_KNM) .Case("lakemont", CK_Lakemont) .Case("k6", CK_K6) .Case("k6-2", CK_K6_2) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/X86.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/X86.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/Targets/X86.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/Targets/X86.h 2017-10-17 14:41:55.000000000 +0000 @@ -203,6 +203,10 @@ /// Knights Landing processor. CK_KNL, + /// \name Knights Mill + /// Knights Mill processor. + CK_KNM, + /// \name Lakemont /// Lakemont microarchitecture based processors. CK_Lakemont, @@ -321,6 +325,7 @@ case CK_SkylakeServer: case CK_Cannonlake: case CK_KNL: + case CK_KNM: case CK_K8: case CK_K8SSE3: case CK_AMDFAM10: @@ -639,7 +644,6 @@ public: WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : WindowsTargetInfo(Triple, Opts) { - WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; bool IsWinCOFF = getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); @@ -700,7 +704,7 @@ public: CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : X86_32TargetInfo(Triple, Opts) { - WCharType = UnsignedShort; + this->WCharType = TargetInfo::UnsignedShort; DoubleAlign = LongLongAlign = 64; resetDataLayout("e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"); } @@ -886,7 +890,6 @@ public: WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : WindowsTargetInfo(Triple, Opts) { - WCharType = UnsignedShort; LongWidth = LongAlign = 32; DoubleAlign = LongLongAlign = 64; IntMaxType = SignedLongLong; @@ -979,8 +982,8 @@ public: CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : X86_64TargetInfo(Triple, Opts) { + this->WCharType = TargetInfo::UnsignedShort; TLSSupported = false; - WCharType = UnsignedShort; } void getTargetDefines(const LangOptions &Opts, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/VirtualFileSystem.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/VirtualFileSystem.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Basic/VirtualFileSystem.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Basic/VirtualFileSystem.cpp 2017-10-17 14:41:54.000000000 +0000 @@ -244,7 +244,7 @@ RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) { if (!EC && Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; - EC = Iter->status(S); + EC = llvm::sys::fs::status(Iter->path(), S, true); CurrentEntry = Status::copyWithNewName(S, Iter->path()); } } @@ -258,7 +258,7 @@ CurrentEntry = Status(); } else { llvm::sys::fs::file_status S; - EC = Iter->status(S); + EC = llvm::sys::fs::status(Iter->path(), S, true); CurrentEntry = Status::copyWithNewName(S, Iter->path()); } return EC; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGAtomic.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGAtomic.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGAtomic.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGAtomic.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -96,9 +96,8 @@ BFI.StorageSize = AtomicSizeInBits; BFI.StorageOffset += OffsetInChars; LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()), - BFI, lvalue.getType(), - lvalue.getBaseInfo()); - LVal.setTBAAInfo(lvalue.getTBAAInfo()); + BFI, lvalue.getType(), lvalue.getBaseInfo(), + lvalue.getTBAAInfo()); AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned); if (AtomicTy.isNull()) { llvm::APInt Size( @@ -205,7 +204,7 @@ addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits()); return LValue::MakeAddr(addr, getValueType(), CGF.getContext(), - LVal.getBaseInfo(), LVal.getTBAAAccessType()); + LVal.getBaseInfo(), LVal.getTBAAInfo()); } /// \brief Emits atomic load. @@ -1227,7 +1226,8 @@ return RValue::get(nullptr); return convertTempToRValue( - Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()), + Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo( + Dest.getAddressSpace())), RValTy, E->getExprLoc()); } @@ -1299,7 +1299,8 @@ assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits()); return convertTempToRValue( - Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()), + Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo( + Dest.getAddressSpace())), RValTy, E->getExprLoc()); } @@ -1346,15 +1347,15 @@ if (LVal.isBitField()) return CGF.EmitLoadOfBitfieldLValue( LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(), - LVal.getBaseInfo()), loc); + LVal.getBaseInfo(), TBAAAccessInfo()), loc); if (LVal.isVectorElt()) return CGF.EmitLoadOfLValue( LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(), - LVal.getBaseInfo()), loc); + LVal.getBaseInfo(), TBAAAccessInfo()), loc); assert(LVal.isExtVectorElt()); return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt( addr, LVal.getExtVectorElts(), LVal.getType(), - LVal.getBaseInfo())); + LVal.getBaseInfo(), TBAAAccessInfo())); } RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, @@ -1425,8 +1426,7 @@ // Other decoration. if (IsVolatile) Load->setVolatile(true); - if (LVal.getTBAAAccessType()) - CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAAccessType()); + CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo()); return Load; } @@ -1671,29 +1671,30 @@ UpdateLVal = LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getBaseInfo(), + AtomicLVal.getTBAAInfo()); DesiredLVal = LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), - AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getType(), AtomicLVal.getBaseInfo(), + AtomicLVal.getTBAAInfo()); } else if (AtomicLVal.isVectorElt()) { UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getBaseInfo(), + AtomicLVal.getTBAAInfo()); DesiredLVal = LValue::MakeVectorElt( DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo()); } else { assert(AtomicLVal.isExtVectorElt()); UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getBaseInfo(), + AtomicLVal.getTBAAInfo()); DesiredLVal = LValue::MakeExtVectorElt( DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo()); } - UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); - DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation()); } // Store new value in the corresponding memory area @@ -1776,20 +1777,19 @@ if (AtomicLVal.isBitField()) { DesiredLVal = LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), - AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getType(), AtomicLVal.getBaseInfo(), + AtomicLVal.getTBAAInfo()); } else if (AtomicLVal.isVectorElt()) { DesiredLVal = LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(), - AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getType(), AtomicLVal.getBaseInfo(), + AtomicLVal.getTBAAInfo()); } else { assert(AtomicLVal.isExtVectorElt()); DesiredLVal = LValue::MakeExtVectorElt( DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo()); + AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo()); } - DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); // Store new value in the corresponding memory area assert(UpdateRVal.isScalar()); CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal); @@ -1942,8 +1942,7 @@ // Other decoration. if (IsVolatile) store->setVolatile(true); - if (dest.getTBAAAccessType()) - CGM.DecorateInstructionWithTBAA(store, dest.getTBAAAccessType()); + CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo()); return; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGBlocks.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGBlocks.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGBlocks.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGBlocks.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -14,11 +14,13 @@ #include "CGBlocks.h" #include "CGDebugInfo.h" #include "CGObjCRuntime.h" +#include "CGOpenCLRuntime.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "ConstantEmitter.h" -#include "clang/CodeGen/ConstantInitBuilder.h" +#include "TargetInfo.h" #include "clang/AST/DeclObjC.h" +#include "clang/CodeGen/ConstantInitBuilder.h" #include "llvm/ADT/SmallSet.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" @@ -302,21 +304,57 @@ static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, SmallVectorImpl &elementTypes) { - // The header is basically 'struct { void *; int; int; void *; void *; }'. - // Assert that that struct is packed. - assert(CGM.getIntSize() <= CGM.getPointerSize()); - assert(CGM.getIntAlign() <= CGM.getPointerAlign()); - assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign())); - - info.BlockAlign = CGM.getPointerAlign(); - info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize(); assert(elementTypes.empty()); - elementTypes.push_back(CGM.VoidPtrTy); - elementTypes.push_back(CGM.IntTy); - elementTypes.push_back(CGM.IntTy); - elementTypes.push_back(CGM.VoidPtrTy); - elementTypes.push_back(CGM.getBlockDescriptorType()); + if (CGM.getLangOpts().OpenCL) { + // The header is basically 'struct { int; int; generic void *; + // custom_fields; }'. Assert that struct is packed. + auto GenericAS = + CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic); + auto GenPtrAlign = + CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8); + auto GenPtrSize = + CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8); + assert(CGM.getIntSize() <= GenPtrSize); + assert(CGM.getIntAlign() <= GenPtrAlign); + assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign)); + elementTypes.push_back(CGM.IntTy); /* total size */ + elementTypes.push_back(CGM.IntTy); /* align */ + elementTypes.push_back( + CGM.getOpenCLRuntime() + .getGenericVoidPointerType()); /* invoke function */ + unsigned Offset = + 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity(); + unsigned BlockAlign = GenPtrAlign.getQuantity(); + if (auto *Helper = + CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { + for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ { + // TargetOpenCLBlockHelp needs to make sure the struct is packed. + // If necessary, add padding fields to the custom fields. + unsigned Align = CGM.getDataLayout().getABITypeAlignment(I); + if (BlockAlign < Align) + BlockAlign = Align; + assert(Offset % Align == 0); + Offset += CGM.getDataLayout().getTypeAllocSize(I); + elementTypes.push_back(I); + } + } + info.BlockAlign = CharUnits::fromQuantity(BlockAlign); + info.BlockSize = CharUnits::fromQuantity(Offset); + } else { + // The header is basically 'struct { void *; int; int; void *; void *; }'. + // Assert that that struct is packed. + assert(CGM.getIntSize() <= CGM.getPointerSize()); + assert(CGM.getIntAlign() <= CGM.getPointerAlign()); + assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign())); + info.BlockAlign = CGM.getPointerAlign(); + info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize(); + elementTypes.push_back(CGM.VoidPtrTy); + elementTypes.push_back(CGM.IntTy); + elementTypes.push_back(CGM.IntTy); + elementTypes.push_back(CGM.VoidPtrTy); + elementTypes.push_back(CGM.getBlockDescriptorType()); + } } static QualType getCaptureFieldType(const CodeGenFunction &CGF, @@ -341,8 +379,12 @@ SmallVector elementTypes; initializeForBlockHeader(CGM, info, elementTypes); - - if (!block->hasCaptures()) { + bool hasNonConstantCustomFields = false; + if (auto *OpenCLHelper = + CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) + hasNonConstantCustomFields = + !OpenCLHelper->areAllCustomFieldValuesConstant(info); + if (!block->hasCaptures() && !hasNonConstantCustomFields) { info.StructureType = llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); info.CanBeGlobal = true; @@ -698,16 +740,27 @@ } /// Emit a block literal expression in the current function. -llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { +llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr, + llvm::Function **InvokeF) { // If the block has no captures, we won't have a pre-computed // layout for it. if (!blockExpr->getBlockDecl()->hasCaptures()) { - if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) + // The block literal is emitted as a global variable, and the block invoke + // function has to be extracted from its initializer. + if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) { + if (InvokeF) { + auto *GV = cast( + cast(Block)->stripPointerCasts()); + auto *BlockInit = cast(GV->getInitializer()); + *InvokeF = cast( + BlockInit->getAggregateElement(2)->stripPointerCasts()); + } return Block; + } CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); computeBlockInfo(CGM, this, blockInfo); blockInfo.BlockExpression = blockExpr; - return EmitBlockLiteral(blockInfo); + return EmitBlockLiteral(blockInfo, InvokeF); } // Find the block info for this block and take ownership of it. @@ -716,18 +769,26 @@ blockExpr->getBlockDecl())); blockInfo->BlockExpression = blockExpr; - return EmitBlockLiteral(*blockInfo); + return EmitBlockLiteral(*blockInfo, InvokeF); } -llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { +llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo, + llvm::Function **InvokeF) { + bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL; + auto GenVoidPtrTy = + IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy; + LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default; + auto GenVoidPtrSize = CharUnits::fromQuantity( + CGM.getTarget().getPointerWidth( + CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) / + 8); // Using the computed layout, generate the actual block function. bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda(); - llvm::Constant *blockFn - = CodeGenFunction(CGM, true).GenerateBlockFunction(CurGD, blockInfo, - LocalDeclMap, - isLambdaConv, - blockInfo.CanBeGlobal); - blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); + auto *InvokeFn = CodeGenFunction(CGM, true).GenerateBlockFunction( + CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal); + if (InvokeF) + *InvokeF = InvokeFn; + auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy); // If there is nothing to capture, we can emit this as a global block. if (blockInfo.CanBeGlobal) @@ -735,26 +796,30 @@ // Otherwise, we have to emit this as a local block. - llvm::Constant *isa = - (!CGM.getContext().getLangOpts().OpenCL) - ? CGM.getNSConcreteStackBlock() - : CGM.getNullPointer(VoidPtrPtrTy, - CGM.getContext().getPointerType( - QualType(CGM.getContext().VoidPtrTy))); - isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy); - - // Build the block descriptor. - llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); - Address blockAddr = blockInfo.LocalAddress; assert(blockAddr.isValid() && "block has no address!"); - // Compute the initial on-stack block flags. - BlockFlags flags = BLOCK_HAS_SIGNATURE; - if (blockInfo.HasCapturedVariableLayout) flags |= BLOCK_HAS_EXTENDED_LAYOUT; - if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; - if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; - if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; + llvm::Constant *isa; + llvm::Constant *descriptor; + BlockFlags flags; + if (!IsOpenCL) { + isa = llvm::ConstantExpr::getBitCast(CGM.getNSConcreteStackBlock(), + VoidPtrTy); + + // Build the block descriptor. + descriptor = buildBlockDescriptor(CGM, blockInfo); + + // Compute the initial on-stack block flags. + flags = BLOCK_HAS_SIGNATURE; + if (blockInfo.HasCapturedVariableLayout) + flags |= BLOCK_HAS_EXTENDED_LAYOUT; + if (blockInfo.NeedsCopyDispose) + flags |= BLOCK_HAS_COPY_DISPOSE; + if (blockInfo.HasCXXObject) + flags |= BLOCK_HAS_CXX_OBJ; + if (blockInfo.UsesStret) + flags |= BLOCK_USE_STRET; + } auto projectField = [&](unsigned index, CharUnits offset, const Twine &name) -> Address { @@ -778,13 +843,33 @@ index++; }; - addHeaderField(isa, getPointerSize(), "block.isa"); - addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()), - getIntSize(), "block.flags"); - addHeaderField(llvm::ConstantInt::get(IntTy, 0), - getIntSize(), "block.reserved"); - addHeaderField(blockFn, getPointerSize(), "block.invoke"); - addHeaderField(descriptor, getPointerSize(), "block.descriptor"); + if (!IsOpenCL) { + addHeaderField(isa, getPointerSize(), "block.isa"); + addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()), + getIntSize(), "block.flags"); + addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(), + "block.reserved"); + } else { + addHeaderField( + llvm::ConstantInt::get(IntTy, blockInfo.BlockSize.getQuantity()), + getIntSize(), "block.size"); + addHeaderField( + llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()), + getIntSize(), "block.align"); + } + addHeaderField(blockFn, GenVoidPtrSize, "block.invoke"); + if (!IsOpenCL) + addHeaderField(descriptor, getPointerSize(), "block.descriptor"); + else if (auto *Helper = + CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { + for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) { + addHeaderField( + I.first, + CharUnits::fromQuantity( + CGM.getDataLayout().getTypeAllocSize(I.first->getType())), + I.second); + } + } } // Finally, capture all the values into the block. @@ -919,9 +1004,8 @@ // FIXME: Pass a specific location for the expr init so that the store is // attributed to a reasonable location - otherwise it may be attributed to // locations of subexpressions in the initialization. - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); EmitExprAsInit(&l2r, &BlockFieldPseudoVar, - MakeAddrLValue(blockField, type, BaseInfo), + MakeAddrLValue(blockField, type, AlignmentSource::Decl), /*captured by init*/ false); } @@ -980,21 +1064,38 @@ llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); - // struct __block_literal_generic { - // void *__isa; - // int __flags; - // int __reserved; - // void (*__invoke)(void *); - // struct __block_descriptor *__descriptor; - // }; - GenericBlockLiteralType = - llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy, - IntTy, IntTy, VoidPtrTy, BlockDescPtrTy); + if (getLangOpts().OpenCL) { + // struct __opencl_block_literal_generic { + // int __size; + // int __align; + // __generic void *__invoke; + // /* custom fields */ + // }; + SmallVector StructFields( + {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()}); + if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { + for (auto I : Helper->getCustomFieldTypes()) + StructFields.push_back(I); + } + GenericBlockLiteralType = llvm::StructType::create( + StructFields, "struct.__opencl_block_literal_generic"); + } else { + // struct __block_literal_generic { + // void *__isa; + // int __flags; + // int __reserved; + // void (*__invoke)(void *); + // struct __block_descriptor *__descriptor; + // }; + GenericBlockLiteralType = + llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy, + IntTy, IntTy, VoidPtrTy, BlockDescPtrTy); + } return GenericBlockLiteralType; } -RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, +RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue) { const BlockPointerType *BPT = E->getCallee()->getType()->getAs(); @@ -1019,8 +1120,8 @@ // Get the function pointer from the literal. llvm::Value *FuncPtr = - Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3); - + Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, + CGM.getLangOpts().OpenCL ? 2 : 3); // Add the block literal. CallArgList Args; @@ -1028,8 +1129,7 @@ QualType VoidPtrQualTy = getContext().VoidPtrTy; llvm::Type *GenericVoidPtrTy = VoidPtrTy; if (getLangOpts().OpenCL) { - GenericVoidPtrTy = Builder.getInt8PtrTy( - getContext().getTargetAddressSpace(LangAS::opencl_generic)); + GenericVoidPtrTy = CGM.getOpenCLRuntime().getGenericVoidPointerType(); VoidPtrQualTy = getContext().getPointerType(getContext().getAddrSpaceQualType( getContext().VoidTy, LangAS::opencl_generic)); @@ -1054,7 +1154,7 @@ llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo); llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); - Func = Builder.CreateBitCast(Func, BlockFTyPtr); + Func = Builder.CreatePointerCast(Func, BlockFTyPtr); // Prepare the callee. CGCallee Callee(CGCalleeInfo(), Func); @@ -1139,27 +1239,37 @@ ConstantInitBuilder builder(CGM); auto fields = builder.beginStruct(); - // isa - fields.add((!CGM.getContext().getLangOpts().OpenCL) - ? CGM.getNSConcreteGlobalBlock() - : CGM.getNullPointer(CGM.VoidPtrPtrTy, - CGM.getContext().getPointerType(QualType( - CGM.getContext().VoidPtrTy)))); - - // __flags - BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; - if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; - - fields.addInt(CGM.IntTy, flags.getBitMask()); - - // Reserved - fields.addInt(CGM.IntTy, 0); + bool IsOpenCL = CGM.getLangOpts().OpenCL; + if (!IsOpenCL) { + // isa + fields.add(CGM.getNSConcreteGlobalBlock()); + + // __flags + BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; + if (blockInfo.UsesStret) + flags |= BLOCK_USE_STRET; + + fields.addInt(CGM.IntTy, flags.getBitMask()); + + // Reserved + fields.addInt(CGM.IntTy, 0); + } else { + fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity()); + fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity()); + } // Function fields.add(blockFn); - // Descriptor - fields.add(buildBlockDescriptor(CGM, blockInfo)); + if (!IsOpenCL) { + // Descriptor + fields.add(buildBlockDescriptor(CGM, blockInfo)); + } else if (auto *Helper = + CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { + for (auto I : Helper->getCustomFieldValues(CGM, blockInfo)) { + fields.add(I); + } + } unsigned AddrSpace = 0; if (CGM.getContext().getLangOpts().OpenCL) @@ -1284,9 +1394,13 @@ fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule()); CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); - if (BuildGlobalBlock) + if (BuildGlobalBlock) { + auto GenVoidPtrTy = getContext().getLangOpts().OpenCL + ? CGM.getOpenCLRuntime().getGenericVoidPointerType() + : VoidPtrTy; buildGlobalBlock(CGM, blockInfo, - llvm::ConstantExpr::getBitCast(fn, VoidPtrTy)); + llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy)); + } // Begin generating the function. StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGBuiltin.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGBuiltin.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGBuiltin.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGBuiltin.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -30,6 +30,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/ConvertUTF.h" #include @@ -663,6 +664,180 @@ return ArgValue; } +/// Get the argument type for arguments to os_log_helper. +static CanQualType getOSLogArgType(ASTContext &C, int Size) { + QualType UnsignedTy = C.getIntTypeForBitwidth(Size * 8, /*Signed=*/false); + return C.getCanonicalType(UnsignedTy); +} + +llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( + const analyze_os_log::OSLogBufferLayout &Layout, + CharUnits BufferAlignment) { + ASTContext &Ctx = getContext(); + + llvm::SmallString<64> Name; + { + raw_svector_ostream OS(Name); + OS << "__os_log_helper"; + OS << "_" << BufferAlignment.getQuantity(); + OS << "_" << int(Layout.getSummaryByte()); + OS << "_" << int(Layout.getNumArgsByte()); + for (const auto &Item : Layout.Items) + OS << "_" << int(Item.getSizeByte()) << "_" + << int(Item.getDescriptorByte()); + } + + if (llvm::Function *F = CGM.getModule().getFunction(Name)) + return F; + + llvm::SmallVector Params; + Params.emplace_back(Ctx, nullptr, SourceLocation(), &Ctx.Idents.get("buffer"), + Ctx.VoidPtrTy, ImplicitParamDecl::Other); + + for (unsigned int I = 0, E = Layout.Items.size(); I < E; ++I) { + char Size = Layout.Items[I].getSizeByte(); + if (!Size) + continue; + + Params.emplace_back( + Ctx, nullptr, SourceLocation(), + &Ctx.Idents.get(std::string("arg") + llvm::to_string(I)), + getOSLogArgType(Ctx, Size), ImplicitParamDecl::Other); + } + + FunctionArgList Args; + for (auto &P : Params) + Args.push_back(&P); + + // The helper function has linkonce_odr linkage to enable the linker to merge + // identical functions. To ensure the merging always happens, 'noinline' is + // attached to the function when compiling with -Oz. + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); + llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI); + llvm::Function *Fn = llvm::Function::Create( + FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, Name, &CGM.getModule()); + Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); + CGM.SetLLVMFunctionAttributes(nullptr, FI, Fn); + CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn); + + // Attach 'noinline' at -Oz. + if (CGM.getCodeGenOpts().OptimizeSize == 2) + Fn->addFnAttr(llvm::Attribute::NoInline); + + auto NL = ApplyDebugLocation::CreateEmpty(*this); + IdentifierInfo *II = &Ctx.Idents.get(Name); + FunctionDecl *FD = FunctionDecl::Create( + Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, + Ctx.VoidTy, nullptr, SC_PrivateExtern, false, false); + + StartFunction(FD, Ctx.VoidTy, Fn, FI, Args); + + // Create a scope with an artificial location for the body of this function. + auto AL = ApplyDebugLocation::CreateArtificial(*this); + + CharUnits Offset; + Address BufAddr(Builder.CreateLoad(GetAddrOfLocalVar(&Params[0]), "buf"), + BufferAlignment); + Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), + Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); + Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), + Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs")); + + unsigned I = 1; + for (const auto &Item : Layout.Items) { + Builder.CreateStore( + Builder.getInt8(Item.getDescriptorByte()), + Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor")); + Builder.CreateStore( + Builder.getInt8(Item.getSizeByte()), + Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize")); + + CharUnits Size = Item.size(); + if (!Size.getQuantity()) + continue; + + Address Arg = GetAddrOfLocalVar(&Params[I]); + Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset, "argData"); + Addr = Builder.CreateBitCast(Addr, Arg.getPointer()->getType(), + "argDataCast"); + Builder.CreateStore(Builder.CreateLoad(Arg), Addr); + Offset += Size; + ++I; + } + + FinishFunction(); + + return Fn; +} + +RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { + assert(E.getNumArgs() >= 2 && + "__builtin_os_log_format takes at least 2 arguments"); + ASTContext &Ctx = getContext(); + analyze_os_log::OSLogBufferLayout Layout; + analyze_os_log::computeOSLogBufferLayout(Ctx, &E, Layout); + Address BufAddr = EmitPointerWithAlignment(E.getArg(0)); + llvm::SmallVector RetainableOperands; + + // Ignore argument 1, the format string. It is not currently used. + CallArgList Args; + Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); + + for (const auto &Item : Layout.Items) { + int Size = Item.getSizeByte(); + if (!Size) + continue; + + llvm::Value *ArgVal; + + if (const Expr *TheExpr = Item.getExpr()) { + ArgVal = EmitScalarExpr(TheExpr, /*Ignore*/ false); + + // Check if this is a retainable type. + if (TheExpr->getType()->isObjCRetainableType()) { + assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar && + "Only scalar can be a ObjC retainable type"); + // Check if the object is constant, if not, save it in + // RetainableOperands. + if (!isa(ArgVal)) + RetainableOperands.push_back(ArgVal); + } + } else { + ArgVal = Builder.getInt32(Item.getConstValue().getQuantity()); + } + + unsigned ArgValSize = + CGM.getDataLayout().getTypeSizeInBits(ArgVal->getType()); + llvm::IntegerType *IntTy = llvm::Type::getIntNTy(getLLVMContext(), + ArgValSize); + ArgVal = Builder.CreateBitOrPointerCast(ArgVal, IntTy); + CanQualType ArgTy = getOSLogArgType(Ctx, Size); + // If ArgVal has type x86_fp80, zero-extend ArgVal. + ArgVal = Builder.CreateZExtOrBitCast(ArgVal, ConvertType(ArgTy)); + Args.add(RValue::get(ArgVal), ArgTy); + } + + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionCall(Ctx.VoidTy, Args); + llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( + Layout, BufAddr.getAlignment()); + EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); + + // Push a clang.arc.use cleanup for each object in RetainableOperands. The + // cleanup will cause the use to appear after the final log call, keeping + // the object valid while it’s held in the log buffer. Note that if there’s + // a release cleanup on the object, it will already be active; since + // cleanups are emitted in reverse order, the use will occur before the + // object is released. + if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount && + CGM.getCodeGenOpts().OptimizationLevel != 0) + for (llvm::Value *Object : RetainableOperands) + pushFullExprCleanup(getARCCleanupKind(), Object); + + return RValue::get(BufAddr.getPointer()); +} + RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -2604,12 +2779,17 @@ // The most basic form of the call with parameters: // queue_t, kernel_enqueue_flags_t, ndrange_t, block(void) Name = "__enqueue_kernel_basic"; - llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, GenericVoidPtrTy}; + llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, GenericVoidPtrTy, + GenericVoidPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef(ArgTys, 4), false); + Int32Ty, llvm::ArrayRef(ArgTys), false); - llvm::Value *Block = Builder.CreatePointerCast( - EmitScalarExpr(E->getArg(3)), GenericVoidPtrTy); + auto Info = + CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3)); + llvm::Value *Kernel = + Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); + llvm::Value *Block = + Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); AttrBuilder B; B.addAttribute(Attribute::ByVal); @@ -2618,7 +2798,7 @@ auto RTCall = Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name, ByValAttrSet), - {Queue, Flags, Range, Block}); + {Queue, Flags, Range, Kernel, Block}); RTCall->setAttributes(ByValAttrSet); return RValue::get(RTCall); } @@ -2650,21 +2830,23 @@ if (E->getArg(3)->getType()->isBlockPointerType()) { // No events passed, but has variadic arguments. Name = "__enqueue_kernel_vaargs"; - auto *Block = Builder.CreatePointerCast(EmitScalarExpr(E->getArg(3)), - GenericVoidPtrTy); + auto Info = + CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3)); + llvm::Value *Kernel = + Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); + auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); auto *PtrToSizeArray = CreateArrayForSizeVar(4); // Create a vector of the arguments, as well as a constant value to // express to the runtime the number of variadic arguments. - std::vector Args = {Queue, - Flags, - Range, - Block, - ConstantInt::get(IntTy, NumArgs - 4), - PtrToSizeArray}; - std::vector ArgTys = {QueueTy, IntTy, - RangeTy, GenericVoidPtrTy, - IntTy, PtrToSizeArray->getType()}; + std::vector Args = { + Queue, Flags, Range, + Kernel, Block, ConstantInt::get(IntTy, NumArgs - 4), + PtrToSizeArray}; + std::vector ArgTys = { + QueueTy, IntTy, RangeTy, + GenericVoidPtrTy, GenericVoidPtrTy, IntTy, + PtrToSizeArray->getType()}; llvm::FunctionType *FTy = llvm::FunctionType::get( Int32Ty, llvm::ArrayRef(ArgTys), false); @@ -2688,15 +2870,19 @@ // Convert to generic address space. EventList = Builder.CreatePointerCast(EventList, EventPtrTy); ClkEvent = Builder.CreatePointerCast(ClkEvent, EventPtrTy); - llvm::Value *Block = Builder.CreatePointerCast( - EmitScalarExpr(E->getArg(6)), GenericVoidPtrTy); + auto Info = + CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(6)); + llvm::Value *Kernel = + Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); + llvm::Value *Block = + Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); std::vector ArgTys = { - QueueTy, Int32Ty, RangeTy, Int32Ty, - EventPtrTy, EventPtrTy, GenericVoidPtrTy}; + QueueTy, Int32Ty, RangeTy, Int32Ty, + EventPtrTy, EventPtrTy, GenericVoidPtrTy, GenericVoidPtrTy}; - std::vector Args = {Queue, Flags, Range, NumEvents, - EventList, ClkEvent, Block}; + std::vector Args = {Queue, Flags, Range, NumEvents, + EventList, ClkEvent, Kernel, Block}; if (NumArgs == 7) { // Has events but no variadics. @@ -2730,24 +2916,30 @@ case Builtin::BIget_kernel_work_group_size: { llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); - Value *Arg = EmitScalarExpr(E->getArg(0)); - Arg = Builder.CreatePointerCast(Arg, GenericVoidPtrTy); + auto Info = + CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(0)); + Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); + Value *Arg = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); return RValue::get(Builder.CreateCall( CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, GenericVoidPtrTy, false), + llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy}, + false), "__get_kernel_work_group_size_impl"), - Arg)); + {Kernel, Arg})); } case Builtin::BIget_kernel_preferred_work_group_size_multiple: { llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); - Value *Arg = EmitScalarExpr(E->getArg(0)); - Arg = Builder.CreatePointerCast(Arg, GenericVoidPtrTy); + auto Info = + CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(0)); + Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); + Value *Arg = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); return RValue::get(Builder.CreateCall( CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, GenericVoidPtrTy, false), + llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy}, + false), "__get_kernel_preferred_work_group_multiple_impl"), - Arg)); + {Kernel, Arg})); } case Builtin::BIget_kernel_max_sub_group_size_for_ndrange: case Builtin::BIget_kernel_sub_group_count_for_ndrange: { @@ -2755,8 +2947,10 @@ getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); llvm::Value *NDRange = NDRangeL.getAddress().getPointer(); - Value *Block = EmitScalarExpr(E->getArg(1)); - Block = Builder.CreatePointerCast(Block, GenericVoidPtrTy); + auto Info = + CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); + Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); + Value *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); const char *Name = BuiltinID == Builtin::BIget_kernel_max_sub_group_size_for_ndrange ? "__get_kernel_max_sub_group_size_for_ndrange_impl" @@ -2764,9 +2958,10 @@ return RValue::get(Builder.CreateCall( CGM.CreateRuntimeFunction( llvm::FunctionType::get( - IntTy, {NDRange->getType(), GenericVoidPtrTy}, false), + IntTy, {NDRange->getType(), GenericVoidPtrTy, GenericVoidPtrTy}, + false), Name), - {NDRange, Block})); + {NDRange, Kernel, Block})); } case Builtin::BI__builtin_store_half: @@ -2801,69 +2996,8 @@ // Fall through - it's already mapped to the intrinsic by GCCBuiltin. break; } - case Builtin::BI__builtin_os_log_format: { - assert(E->getNumArgs() >= 2 && - "__builtin_os_log_format takes at least 2 arguments"); - analyze_os_log::OSLogBufferLayout Layout; - analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout); - Address BufAddr = EmitPointerWithAlignment(E->getArg(0)); - // Ignore argument 1, the format string. It is not currently used. - CharUnits Offset; - Builder.CreateStore( - Builder.getInt8(Layout.getSummaryByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); - Builder.CreateStore( - Builder.getInt8(Layout.getNumArgsByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs")); - - llvm::SmallVector RetainableOperands; - for (const auto &Item : Layout.Items) { - Builder.CreateStore( - Builder.getInt8(Item.getDescriptorByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor")); - Builder.CreateStore( - Builder.getInt8(Item.getSizeByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize")); - Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset); - if (const Expr *TheExpr = Item.getExpr()) { - Addr = Builder.CreateElementBitCast( - Addr, ConvertTypeForMem(TheExpr->getType())); - // Check if this is a retainable type. - if (TheExpr->getType()->isObjCRetainableType()) { - assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar && - "Only scalar can be a ObjC retainable type"); - llvm::Value *SV = EmitScalarExpr(TheExpr, /*Ignore*/ false); - RValue RV = RValue::get(SV); - LValue LV = MakeAddrLValue(Addr, TheExpr->getType()); - EmitStoreThroughLValue(RV, LV); - // Check if the object is constant, if not, save it in - // RetainableOperands. - if (!isa(SV)) - RetainableOperands.push_back(SV); - } else { - EmitAnyExprToMem(TheExpr, Addr, Qualifiers(), /*isInit*/ true); - } - } else { - Addr = Builder.CreateElementBitCast(Addr, Int32Ty); - Builder.CreateStore( - Builder.getInt32(Item.getConstValue().getQuantity()), Addr); - } - Offset += Item.size(); - } - - // Push a clang.arc.use cleanup for each object in RetainableOperands. The - // cleanup will cause the use to appear after the final log call, keeping - // the object valid while it's held in the log buffer. Note that if there's - // a release cleanup on the object, it will already be active; since - // cleanups are emitted in reverse order, the use will occur before the - // object is released. - if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount && - CGM.getCodeGenOpts().OptimizationLevel != 0) - for (llvm::Value *object : RetainableOperands) - pushFullExprCleanup(getARCCleanupKind(), object); - - return RValue::get(BufAddr.getPointer()); - } + case Builtin::BI__builtin_os_log_format: + return emitBuiltinOSLogFormat(*E); case Builtin::BI__builtin_os_log_format_buffer_size: { analyze_os_log::OSLogBufferLayout Layout; @@ -7387,6 +7521,7 @@ INTEL_KNL, AMD_BTVER1, AMD_BTVER2, + AMDFAM17H, CPU_SUBTYPE_START, INTEL_COREI7_NEHALEM, INTEL_COREI7_WESTMERE, @@ -7413,6 +7548,7 @@ .Case("amdfam10", AMDFAM10H) .Case("amdfam15h", AMDFAM15H) .Case("amdfam15", AMDFAM15H) + .Case("amdfam17h", AMDFAM17H) .Case("atom", INTEL_BONNELL) .Case("barcelona", AMDFAM10H_BARCELONA) .Case("bdver1", AMDFAM15H_BDVER1) @@ -7594,12 +7730,21 @@ return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0)); } +Value *CodeGenFunction::EmitX86CpuInit() { + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, + /*Variadic*/ false); + llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, "__cpu_indicator_init"); + return Builder.CreateCall(Func); +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (BuiltinID == X86::BI__builtin_cpu_is) return EmitX86CpuIs(E); if (BuiltinID == X86::BI__builtin_cpu_supports) return EmitX86CpuSupports(E); + if (BuiltinID == X86::BI__builtin_cpu_init) + return EmitX86CpuInit(); SmallVector Ops; @@ -7651,13 +7796,6 @@ switch (BuiltinID) { default: return nullptr; - case X86::BI__builtin_cpu_init: { - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, - /*Variadic*/false); - llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, - "__cpu_indicator_init"); - return Builder.CreateCall(Func); - } case X86::BI_mm_prefetch: { Value *Address = Ops[0]; Value *RW = ConstantInt::get(Int32Ty, 0); @@ -8987,6 +9125,15 @@ CI->setConvergent(); return CI; } + case AMDGPU::BI__builtin_amdgcn_read_exec_lo: + case AMDGPU::BI__builtin_amdgcn_read_exec_hi: { + StringRef RegName = BuiltinID == AMDGPU::BI__builtin_amdgcn_read_exec_lo ? + "exec_lo" : "exec_hi"; + CallInst *CI = cast( + EmitSpecialRegisterBuiltin(*this, E, Int32Ty, Int32Ty, true, RegName)); + CI->setConvergent(); + return CI; + } // amdgcn workitem case AMDGPU::BI__builtin_amdgcn_workitem_id_x: @@ -9604,6 +9751,204 @@ Builder.CreateStore(Pred, PredOutPtr); return Builder.CreateExtractValue(ResultPair, 0); } + case NVPTX::BI__hmma_m16n16k16_ld_a: + case NVPTX::BI__hmma_m16n16k16_ld_b: + case NVPTX::BI__hmma_m16n16k16_ld_c_f16: + case NVPTX::BI__hmma_m16n16k16_ld_c_f32: { + Address Dst = EmitPointerWithAlignment(E->getArg(0)); + Value *Src = EmitScalarExpr(E->getArg(1)); + Value *Ldm = EmitScalarExpr(E->getArg(2)); + llvm::APSInt isColMajorArg; + if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) + return nullptr; + bool isColMajor = isColMajorArg.getSExtValue(); + unsigned IID; + unsigned NumResults; + switch (BuiltinID) { + case NVPTX::BI__hmma_m16n16k16_ld_a: + IID = isColMajor ? Intrinsic::nvvm_wmma_load_a_f16_col_stride + : Intrinsic::nvvm_wmma_load_a_f16_row_stride; + NumResults = 8; + break; + case NVPTX::BI__hmma_m16n16k16_ld_b: + IID = isColMajor ? Intrinsic::nvvm_wmma_load_b_f16_col_stride + : Intrinsic::nvvm_wmma_load_b_f16_row_stride; + NumResults = 8; + break; + case NVPTX::BI__hmma_m16n16k16_ld_c_f16: + IID = isColMajor ? Intrinsic::nvvm_wmma_load_c_f16_col_stride + : Intrinsic::nvvm_wmma_load_c_f16_row_stride; + NumResults = 4; + break; + case NVPTX::BI__hmma_m16n16k16_ld_c_f32: + IID = isColMajor ? Intrinsic::nvvm_wmma_load_c_f32_col_stride + : Intrinsic::nvvm_wmma_load_c_f32_row_stride; + NumResults = 8; + break; + default: + llvm_unreachable("Unexpected builtin ID."); + } + Value *Result = + Builder.CreateCall(CGM.getIntrinsic(IID), + {Builder.CreatePointerCast(Src, VoidPtrTy), Ldm}); + + // Save returned values. + for (unsigned i = 0; i < NumResults; ++i) { + Builder.CreateAlignedStore( + Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), + Dst.getElementType()), + Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), + CharUnits::fromQuantity(4)); + } + return Result; + } + + case NVPTX::BI__hmma_m16n16k16_st_c_f16: + case NVPTX::BI__hmma_m16n16k16_st_c_f32: { + Value *Dst = EmitScalarExpr(E->getArg(0)); + Address Src = EmitPointerWithAlignment(E->getArg(1)); + Value *Ldm = EmitScalarExpr(E->getArg(2)); + llvm::APSInt isColMajorArg; + if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) + return nullptr; + bool isColMajor = isColMajorArg.getSExtValue(); + unsigned IID; + unsigned NumResults = 8; + // PTX Instructions (and LLVM instrinsics) are defined for slice _d_, yet + // for some reason nvcc builtins use _c_. + switch (BuiltinID) { + case NVPTX::BI__hmma_m16n16k16_st_c_f16: + IID = isColMajor ? Intrinsic::nvvm_wmma_store_d_f16_col_stride + : Intrinsic::nvvm_wmma_store_d_f16_row_stride; + NumResults = 4; + break; + case NVPTX::BI__hmma_m16n16k16_st_c_f32: + IID = isColMajor ? Intrinsic::nvvm_wmma_store_d_f32_col_stride + : Intrinsic::nvvm_wmma_store_d_f32_row_stride; + break; + default: + llvm_unreachable("Unexpected builtin ID."); + } + Function *Intrinsic = CGM.getIntrinsic(IID); + llvm::Type *ParamType = Intrinsic->getFunctionType()->getParamType(1); + SmallVector Values; + Values.push_back(Builder.CreatePointerCast(Dst, VoidPtrTy)); + for (unsigned i = 0; i < NumResults; ++i) { + Value *V = Builder.CreateAlignedLoad( + Builder.CreateGEP(Src.getPointer(), llvm::ConstantInt::get(IntTy, i)), + CharUnits::fromQuantity(4)); + Values.push_back(Builder.CreateBitCast(V, ParamType)); + } + Values.push_back(Ldm); + Value *Result = Builder.CreateCall(Intrinsic, Values); + return Result; + } + + // BI__hmma_m16n16k16_mma_(d, a, b, c, layout, satf) + // --> Intrinsic::nvvm_wmma_mma_sync + case NVPTX::BI__hmma_m16n16k16_mma_f16f16: + case NVPTX::BI__hmma_m16n16k16_mma_f32f16: + case NVPTX::BI__hmma_m16n16k16_mma_f32f32: + case NVPTX::BI__hmma_m16n16k16_mma_f16f32: { + Address Dst = EmitPointerWithAlignment(E->getArg(0)); + Address SrcA = EmitPointerWithAlignment(E->getArg(1)); + Address SrcB = EmitPointerWithAlignment(E->getArg(2)); + Address SrcC = EmitPointerWithAlignment(E->getArg(3)); + llvm::APSInt LayoutArg; + if (!E->getArg(4)->isIntegerConstantExpr(LayoutArg, getContext())) + return nullptr; + int Layout = LayoutArg.getSExtValue(); + if (Layout < 0 || Layout > 3) + return nullptr; + llvm::APSInt SatfArg; + if (!E->getArg(5)->isIntegerConstantExpr(SatfArg, getContext())) + return nullptr; + bool Satf = SatfArg.getSExtValue(); + + // clang-format off +#define MMA_VARIANTS(type) {{ \ + Intrinsic::nvvm_wmma_mma_sync_row_row_##type, \ + Intrinsic::nvvm_wmma_mma_sync_row_row_##type##_satfinite, \ + Intrinsic::nvvm_wmma_mma_sync_row_col_##type, \ + Intrinsic::nvvm_wmma_mma_sync_row_col_##type##_satfinite, \ + Intrinsic::nvvm_wmma_mma_sync_col_row_##type, \ + Intrinsic::nvvm_wmma_mma_sync_col_row_##type##_satfinite, \ + Intrinsic::nvvm_wmma_mma_sync_col_col_##type, \ + Intrinsic::nvvm_wmma_mma_sync_col_col_##type##_satfinite \ + }} + // clang-format on + + auto getMMAIntrinsic = [Layout, Satf](std::array Variants) { + unsigned Index = Layout * 2 + Satf; + assert(Index < 8); + return Variants[Index]; + }; + unsigned IID; + unsigned NumEltsC; + unsigned NumEltsD; + switch (BuiltinID) { + case NVPTX::BI__hmma_m16n16k16_mma_f16f16: + IID = getMMAIntrinsic(MMA_VARIANTS(f16_f16)); + NumEltsC = 4; + NumEltsD = 4; + break; + case NVPTX::BI__hmma_m16n16k16_mma_f32f16: + IID = getMMAIntrinsic(MMA_VARIANTS(f32_f16)); + NumEltsC = 4; + NumEltsD = 8; + break; + case NVPTX::BI__hmma_m16n16k16_mma_f16f32: + IID = getMMAIntrinsic(MMA_VARIANTS(f16_f32)); + NumEltsC = 8; + NumEltsD = 4; + break; + case NVPTX::BI__hmma_m16n16k16_mma_f32f32: + IID = getMMAIntrinsic(MMA_VARIANTS(f32_f32)); + NumEltsC = 8; + NumEltsD = 8; + break; + default: + llvm_unreachable("Unexpected builtin ID."); + } +#undef MMA_VARIANTS + + SmallVector Values; + Function *Intrinsic = CGM.getIntrinsic(IID); + llvm::Type *ABType = Intrinsic->getFunctionType()->getParamType(0); + // Load A + for (unsigned i = 0; i < 8; ++i) { + Value *V = Builder.CreateAlignedLoad( + Builder.CreateGEP(SrcA.getPointer(), + llvm::ConstantInt::get(IntTy, i)), + CharUnits::fromQuantity(4)); + Values.push_back(Builder.CreateBitCast(V, ABType)); + } + // Load B + for (unsigned i = 0; i < 8; ++i) { + Value *V = Builder.CreateAlignedLoad( + Builder.CreateGEP(SrcB.getPointer(), + llvm::ConstantInt::get(IntTy, i)), + CharUnits::fromQuantity(4)); + Values.push_back(Builder.CreateBitCast(V, ABType)); + } + // Load C + llvm::Type *CType = Intrinsic->getFunctionType()->getParamType(16); + for (unsigned i = 0; i < NumEltsC; ++i) { + Value *V = Builder.CreateAlignedLoad( + Builder.CreateGEP(SrcC.getPointer(), + llvm::ConstantInt::get(IntTy, i)), + CharUnits::fromQuantity(4)); + Values.push_back(Builder.CreateBitCast(V, CType)); + } + Value *Result = Builder.CreateCall(Intrinsic, Values); + llvm::Type *DType = Dst.getElementType(); + for (unsigned i = 0; i < NumEltsD; ++i) + Builder.CreateAlignedStore( + Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), + Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), + CharUnits::fromQuantity(4)); + return Result; + } default: return nullptr; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGCall.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGCall.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGCall.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGCall.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1750,13 +1750,16 @@ FuncAttrs.addAttribute("backchain"); } - if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { - // Conservatively, mark all functions and calls in CUDA as convergent - // (meaning, they may call an intrinsically convergent op, such as - // __syncthreads(), and so can't have certain optimizations applied around - // them). LLVM will remove this attribute where it safely can. + if (getLangOpts().assumeFunctionsAreConvergent()) { + // Conservatively, mark all functions and calls in CUDA and OpenCL as + // convergent (meaning, they may call an intrinsically convergent op, such + // as __syncthreads() / barrier(), and so can't have certain optimizations + // applied around them). LLVM will remove this attribute where it safely + // can. FuncAttrs.addAttribute(llvm::Attribute::Convergent); + } + if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { // Exceptions aren't supported in CUDA device code. FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGClass.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGClass.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGClass.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGClass.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -129,14 +129,16 @@ CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base, llvm::Value *memberPtr, const MemberPointerType *memberPtrType, - LValueBaseInfo *BaseInfo) { + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { // Ask the ABI to compute the actual address. llvm::Value *ptr = CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base, memberPtr, memberPtrType); QualType memberType = memberPtrType->getPointeeType(); - CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo); + CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo, + TBAAInfo); memberAlign = CGM.getDynamicOffsetAlignment(base.getAlignment(), memberPtrType->getClass()->getAsCXXRecordDecl(), @@ -1413,10 +1415,11 @@ // possible to delegate the destructor body to the complete // destructor. Do so. if (DtorType == Dtor_Deleting) { + RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); - EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); - PopCleanupBlock(); + if (HaveInsertPoint()) + EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, + /*Delegating=*/false, LoadCXXThisAddress()); return; } @@ -1512,6 +1515,13 @@ } namespace { + llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF, + const CXXDestructorDecl *DD) { + if (Expr *ThisArg = DD->getOperatorDeleteThisArg()) + return CGF.EmitScalarExpr(ThisArg); + return CGF.LoadCXXThis(); + } + /// Call the operator delete associated with the current destructor. struct CallDtorDelete final : EHScopeStack::Cleanup { CallDtorDelete() {} @@ -1519,11 +1529,38 @@ void Emit(CodeGenFunction &CGF, Flags flags) override { const CXXDestructorDecl *Dtor = cast(CGF.CurCodeDecl); const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), + LoadThisForDtorDelete(CGF, Dtor), CGF.getContext().getTagDeclType(ClassDecl)); } }; + void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF, + llvm::Value *ShouldDeleteCondition, + bool ReturnAfterDelete) { + llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); + llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); + llvm::Value *ShouldCallDelete + = CGF.Builder.CreateIsNull(ShouldDeleteCondition); + CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); + + CGF.EmitBlock(callDeleteBB); + const CXXDestructorDecl *Dtor = cast(CGF.CurCodeDecl); + const CXXRecordDecl *ClassDecl = Dtor->getParent(); + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), + LoadThisForDtorDelete(CGF, Dtor), + CGF.getContext().getTagDeclType(ClassDecl)); + assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() == + ReturnAfterDelete && + "unexpected value for ReturnAfterDelete"); + if (ReturnAfterDelete) + CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); + else + CGF.Builder.CreateBr(continueBB); + + CGF.EmitBlock(continueBB); + } + struct CallDtorDeleteConditional final : EHScopeStack::Cleanup { llvm::Value *ShouldDeleteCondition; @@ -1534,20 +1571,8 @@ } void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); - llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); - llvm::Value *ShouldCallDelete - = CGF.Builder.CreateIsNull(ShouldDeleteCondition); - CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); - - CGF.EmitBlock(callDeleteBB); - const CXXDestructorDecl *Dtor = cast(CGF.CurCodeDecl); - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), - CGF.getContext().getTagDeclType(ClassDecl)); - CGF.Builder.CreateBr(continueBB); - - CGF.EmitBlock(continueBB); + EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition, + /*ReturnAfterDelete*/false); } }; @@ -1706,6 +1731,9 @@ /// \brief Emit all code that comes at the end of class's /// destructor. This is to call destructors on members and base classes /// in reverse order of their construction. +/// +/// For a deleting destructor, this also handles the case where a destroying +/// operator delete completely overrides the definition. void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, CXXDtorType DtorType) { assert((!DD->isTrivial() || DD->hasAttr()) && @@ -1718,11 +1746,23 @@ "operator delete missing - EnterDtorCleanups"); if (CXXStructorImplicitParamValue) { // If there is an implicit param to the deleting dtor, it's a boolean - // telling whether we should call delete at the end of the dtor. - EHStack.pushCleanup( - NormalAndEHCleanup, CXXStructorImplicitParamValue); + // telling whether this is a deleting destructor. + if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) + EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue, + /*ReturnAfterDelete*/true); + else + EHStack.pushCleanup( + NormalAndEHCleanup, CXXStructorImplicitParamValue); } else { - EHStack.pushCleanup(NormalAndEHCleanup); + if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) { + const CXXRecordDecl *ClassDecl = DD->getParent(); + EmitDeleteCall(DD->getOperatorDelete(), + LoadThisForDtorDelete(*this, DD), + getContext().getTagDeclType(ClassDecl)); + EmitBranchThroughCleanup(ReturnBlock); + } else { + EHStack.pushCleanup(NormalAndEHCleanup); + } } return; } @@ -2383,7 +2423,7 @@ VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy); llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField); - CGM.DecorateInstructionWithTBAA(Store, CGM.getTBAAInfoForVTablePtr()); + CGM.DecorateInstructionWithTBAA(Store, CGM.getTBAAVTablePtrAccessInfo()); if (CGM.getCodeGenOpts().OptimizationLevel > 0 && CGM.getCodeGenOpts().StrictVTablePointers) CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass); @@ -2477,7 +2517,7 @@ const CXXRecordDecl *RD) { Address VTablePtrSrc = Builder.CreateElementBitCast(This, VTableTy); llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable"); - CGM.DecorateInstructionWithTBAA(VTable, CGM.getTBAAInfoForVTablePtr()); + CGM.DecorateInstructionWithTBAA(VTable, CGM.getTBAAVTablePtrAccessInfo()); if (CGM.getCodeGenOpts().OptimizationLevel > 0 && CGM.getCodeGenOpts().StrictVTablePointers) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGCXX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -110,16 +110,14 @@ return true; return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base), - GlobalDecl(BaseD, Dtor_Base), - false); + GlobalDecl(BaseD, Dtor_Base)); } /// Try to emit a definition as a global alias for another definition. /// If \p InEveryTU is true, we know that an equivalent alias can be produced /// in every translation unit. bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, - GlobalDecl TargetDecl, - bool InEveryTU) { + GlobalDecl TargetDecl) { if (!getCodeGenOpts().CXXCtorDtorAliases) return true; @@ -134,11 +132,6 @@ llvm::GlobalValue::LinkageTypes TargetLinkage = getFunctionLinkage(TargetDecl); - // available_externally definitions aren't real definitions, so we cannot - // create an alias to one. - if (TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage) - return true; - // Check if we have it already. StringRef MangledName = getMangledName(AliasDecl); llvm::GlobalValue *Entry = GetGlobalValue(MangledName); @@ -161,7 +154,14 @@ // Instead of creating as alias to a linkonce_odr, replace all of the uses // of the aliasee. - if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) { + if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) && + !(TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage && + TargetDecl.getDecl()->hasAttr())) { + // FIXME: An extern template instantiation will create functions with + // linkage "AvailableExternally". In libc++, some classes also define + // members with attribute "AlwaysInline" and expect no reference to + // be generated. It is desirable to reenable this optimisation after + // corresponding LLVM changes. addReplacement(MangledName, Aliasee); return false; } @@ -176,13 +176,11 @@ return true; } - if (!InEveryTU) { - // If we don't have a definition for the destructor yet, don't - // emit. We can't emit aliases to declarations; that's just not - // how aliases work. - if (Ref->isDeclaration()) - return true; - } + // If we don't have a definition for the destructor yet or the definition is + // avaialable_externally, don't emit an alias. We can't emit aliases to + // declarations; that's just not how aliases work. + if (Ref->isDeclarationForLinker()) + return true; // Don't create an alias to a linker weak symbol. This avoids producing // different COMDATs in different TUs. Another option would be to diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -222,7 +222,7 @@ Name = getStaticDeclName(*this, D); llvm::Type *LTy = getTypes().ConvertTypeForMem(Ty); - unsigned AS = GetGlobalVarAddressSpace(&D); + LangAS AS = GetGlobalVarAddressSpace(&D); unsigned TargetAS = getContext().getTargetAddressSpace(AS); // Local address space cannot have an initializer. @@ -252,7 +252,7 @@ } // Make sure the result is of the correct type. - unsigned ExpectedAS = Ty.getAddressSpace(); + LangAS ExpectedAS = Ty.getAddressSpace(); llvm::Constant *Addr = GV; if (AS != ExpectedAS) { Addr = getTargetCodeGenInfo().performAddrSpaceCast( @@ -956,7 +956,9 @@ CodeGenFunction::AutoVarEmission CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { QualType Ty = D.getType(); - assert(Ty.getAddressSpace() == LangAS::Default); + assert( + Ty.getAddressSpace() == LangAS::Default || + (Ty.getAddressSpace() == LangAS::opencl_private && getLangOpts().OpenCL)); AutoVarEmission emission(D); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGException.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGException.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGException.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGException.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -225,7 +225,12 @@ } const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) { - return get(CGF.CGM, dyn_cast_or_null(CGF.CurCodeDecl)); + const auto *FD = CGF.CurCodeDecl; + // For outlined finallys and filters, use the SEH personality in case they + // contain more SEH. This mostly only affects finallys. Filters could + // hypothetically use gnu statement expressions to sneak in nested SEH. + FD = FD ? FD : CGF.CurSEHParent; + return get(CGF.CGM, dyn_cast_or_null(FD)); } static llvm::Constant *getPersonalityFn(CodeGenModule &CGM, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprComplex.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprComplex.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprComplex.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprComplex.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -775,7 +775,6 @@ if (!LHSi) LibCallOp.LHS.second = llvm::Constant::getNullValue(LHSr->getType()); - StringRef LibCallName; switch (LHSr->getType()->getTypeID()) { default: llvm_unreachable("Unsupported floating point type!"); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprConstant.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprConstant.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprConstant.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprConstant.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -612,7 +612,7 @@ CGM.getAddrOfConstantCompoundLiteralIfEmitted(E)) return ConstantAddress(Addr, Align); - unsigned addressSpace = E->getType().getAddressSpace(); + LangAS addressSpace = E->getType().getAddressSpace(); ConstantEmitter emitter(CGM, CGF); llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(), @@ -725,8 +725,8 @@ case CK_AddressSpaceConversion: { auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType()); if (!C) return nullptr; - unsigned destAS = E->getType()->getPointeeType().getAddressSpace(); - unsigned srcAS = subExpr->getType()->getPointeeType().getAddressSpace(); + LangAS destAS = E->getType()->getPointeeType().getAddressSpace(); + LangAS srcAS = subExpr->getType()->getPointeeType().getAddressSpace(); llvm::Type *destTy = ConvertType(E->getType()); return CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGM, C, srcAS, destAS, destTy); @@ -1184,14 +1184,14 @@ } llvm::Constant *ConstantEmitter::tryEmitForInitializer(const Expr *E, - unsigned destAddrSpace, + LangAS destAddrSpace, QualType destType) { initializeNonAbstract(destAddrSpace); return markIfFailed(tryEmitPrivateForMemory(E, destType)); } llvm::Constant *ConstantEmitter::emitForInitializer(const APValue &value, - unsigned destAddrSpace, + LangAS destAddrSpace, QualType destType) { initializeNonAbstract(destAddrSpace); auto C = tryEmitPrivateForMemory(value, destType); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExpr.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExpr.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExpr.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExpr.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -412,14 +412,12 @@ // dynamic initialization or a cleanup and we can just return the address // of the temporary. if (Var->hasInitializer()) - return MakeAddrLValue(Object, M->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); Var->setInitializer(CGM.EmitNullConstant(E->getType())); } LValue RefTempDst = MakeAddrLValue(Object, M->getType(), - LValueBaseInfo(AlignmentSource::Decl, - false)); + AlignmentSource::Decl); switch (getEvaluationKind(E->getType())) { default: llvm_unreachable("expected scalar or aggregate expression"); @@ -506,8 +504,7 @@ break; case SubobjectAdjustment::FieldAdjustment: { - LValue LV = MakeAddrLValue(Object, E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + LValue LV = MakeAddrLValue(Object, E->getType(), AlignmentSource::Decl); LV = EmitLValueForField(LV, Adjustment.Field); assert(LV.isSimple() && "materialized temporary field is not a simple lvalue"); @@ -524,8 +521,7 @@ } } - return MakeAddrLValue(Object, M->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); } RValue @@ -920,7 +916,8 @@ /// EmitPointerWithAlignment - Given an expression of pointer type, try to /// derive a more accurate bound on the alignment of the pointer. Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, - LValueBaseInfo *BaseInfo) { + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { // We allow this with ObjC object pointers because of fragile ABIs. assert(E->getType()->isPointerType() || E->getType()->isObjCObjectPointerType()); @@ -940,20 +937,30 @@ if (PtrTy->getPointeeType()->isVoidType()) break; - LValueBaseInfo InnerInfo; - Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerInfo); - if (BaseInfo) *BaseInfo = InnerInfo; - - // If this is an explicit bitcast, and the source l-value is - // opaque, honor the alignment of the casted-to type. - if (isa(CE) && - InnerInfo.getAlignmentSource() != AlignmentSource::Decl) { - LValueBaseInfo ExpInfo; + LValueBaseInfo InnerBaseInfo; + TBAAAccessInfo InnerTBAAInfo; + Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), + &InnerBaseInfo, + &InnerTBAAInfo); + if (BaseInfo) *BaseInfo = InnerBaseInfo; + if (TBAAInfo) *TBAAInfo = InnerTBAAInfo; + + if (isa(CE)) { + LValueBaseInfo TargetTypeBaseInfo; + TBAAAccessInfo TargetTypeTBAAInfo; CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), - &ExpInfo); - if (BaseInfo) - BaseInfo->mergeForCast(ExpInfo); - Addr = Address(Addr.getPointer(), Align); + &TargetTypeBaseInfo, + &TargetTypeTBAAInfo); + if (TBAAInfo) + *TBAAInfo = CGM.mergeTBAAInfoForCast(*TBAAInfo, + TargetTypeTBAAInfo); + // If the source l-value is opaque, honor the alignment of the + // casted-to type. + if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { + if (BaseInfo) + BaseInfo->mergeForCast(TargetTypeBaseInfo); + Addr = Address(Addr.getPointer(), Align); + } } if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) && @@ -973,12 +980,13 @@ // Array-to-pointer decay. case CK_ArrayToPointerDecay: - return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo); + return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo, TBAAInfo); // Derived-to-base conversions. case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { - Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo); + Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo, + TBAAInfo); auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl(); return GetAddressOfBaseClass(Addr, Derived, CE->path_begin(), CE->path_end(), @@ -998,6 +1006,7 @@ if (UO->getOpcode() == UO_AddrOf) { LValue LV = EmitLValue(UO->getSubExpr()); if (BaseInfo) *BaseInfo = LV.getBaseInfo(); + if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo(); return LV.getAddress(); } } @@ -1005,7 +1014,8 @@ // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo); + CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, + TBAAInfo); return Address(EmitScalarExpr(E), Align); } @@ -1174,8 +1184,7 @@ llvm::Value *V = LV.getPointer(); Scope.ForceCleanup({&V}); return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(), - getContext(), LV.getBaseInfo(), - LV.getTBAAAccessType()); + getContext(), LV.getBaseInfo(), LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a // bitfield lvalue or some other non-simple lvalue? @@ -1514,7 +1523,7 @@ // Atomic operations have to be done on integral types. LValue AtomicLValue = - LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo.AccessType); + LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo); if (Ty->isAtomicType() || LValueIsSuitableForInlineAtomic(AtomicLValue)) { return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal(); } @@ -1525,14 +1534,10 @@ Load->getContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1))); Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); } - if (TBAAInfo.AccessType) { - bool MayAlias = BaseInfo.getMayAlias(); - llvm::MDNode *TBAA = MayAlias - ? CGM.getTBAAMayAliasTypeInfo() - : CGM.getTBAAStructTagInfo(TBAAInfo); - if (TBAA) - CGM.DecorateInstructionWithTBAA(Load, TBAA, MayAlias); - } + + if (BaseInfo.getMayAlias()) + TBAAInfo = CGM.getTBAAMayAliasAccessInfo(); + CGM.DecorateInstructionWithTBAA(Load, TBAAInfo); if (EmitScalarRangeCheck(Load, Ty, Loc)) { // In order to prevent the optimizer from throwing away the check, don't @@ -1599,7 +1604,7 @@ Value = EmitToMemory(Value, Ty); LValue AtomicLValue = - LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo.AccessType); + LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo); if (Ty->isAtomicType() || (!isInit && LValueIsSuitableForInlineAtomic(AtomicLValue))) { EmitAtomicStore(RValue::get(Value), AtomicLValue, isInit); @@ -1613,14 +1618,10 @@ llvm::ConstantAsMetadata::get(Builder.getInt32(1))); Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); } - if (TBAAInfo.AccessType) { - bool MayAlias = BaseInfo.getMayAlias(); - llvm::MDNode *TBAA = MayAlias - ? CGM.getTBAAMayAliasTypeInfo() - : CGM.getTBAAStructTagInfo(TBAAInfo); - if (TBAA) - CGM.DecorateInstructionWithTBAA(Store, TBAA, MayAlias); - } + + if (BaseInfo.getMayAlias()) + TBAAInfo = CGM.getTBAAMayAliasAccessInfo(); + CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, @@ -2157,39 +2158,43 @@ llvm::Type *RealVarTy, SourceLocation Loc) { Addr = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, Addr, Loc); Addr = CGF.Builder.CreateElementBitCast(Addr, RealVarTy); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - return CGF.MakeAddrLValue(Addr, T, BaseInfo); + return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); } Address CodeGenFunction::EmitLoadOfReference(Address Addr, const ReferenceType *RefTy, - LValueBaseInfo *BaseInfo) { + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { llvm::Value *Ptr = Builder.CreateLoad(Addr); return Address(Ptr, getNaturalTypeAlignment(RefTy->getPointeeType(), - BaseInfo, /*forPointee*/ true)); + BaseInfo, TBAAInfo, + /* forPointeeType= */ true)); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr, const ReferenceType *RefTy) { LValueBaseInfo BaseInfo; - Address Addr = EmitLoadOfReference(RefAddr, RefTy, &BaseInfo); - return MakeAddrLValue(Addr, RefTy->getPointeeType(), BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Addr = EmitLoadOfReference(RefAddr, RefTy, &BaseInfo, &TBAAInfo); + return MakeAddrLValue(Addr, RefTy->getPointeeType(), BaseInfo, TBAAInfo); } Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, - LValueBaseInfo *BaseInfo) { + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(), - BaseInfo, + BaseInfo, TBAAInfo, /*forPointeeType=*/true)); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, const PointerType *PtrTy) { LValueBaseInfo BaseInfo; - Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo); - return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo, &TBAAInfo); + return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo, TBAAInfo); } static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, @@ -2215,8 +2220,7 @@ if (auto RefTy = VD->getType()->getAs()) { LV = CGF.EmitLoadOfReferenceLValue(Addr, RefTy); } else { - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - LV = CGF.MakeAddrLValue(Addr, T, BaseInfo); + LV = CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); } setObjCGCLValueClass(CGF.getContext(), E, LV); return LV; @@ -2250,8 +2254,8 @@ const Expr *E, const FunctionDecl *FD) { llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD); CharUnits Alignment = CGF.getContext().getDeclAlign(FD); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - return CGF.MakeAddrLValue(V, E->getType(), Alignment, BaseInfo); + return CGF.MakeAddrLValue(V, E->getType(), Alignment, + AlignmentSource::Decl); } static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD, @@ -2306,8 +2310,12 @@ VD->isUsableInConstantExpressions(getContext()) && VD->checkInitIsICE() && // Do not emit if it is private OpenMP variable. - !(E->refersToEnclosingVariableOrCapture() && CapturedStmtInfo && - LocalDeclMap.count(VD))) { + !(E->refersToEnclosingVariableOrCapture() && + ((CapturedStmtInfo && + (LocalDeclMap.count(VD->getCanonicalDecl()) || + CapturedStmtInfo->lookup(VD->getCanonicalDecl()))) || + LambdaCaptureFields.lookup(VD->getCanonicalDecl()) || + isa(CurCodeDecl)))) { llvm::Constant *Val = ConstantEmitter(*this).emitAbstract(E->getLocation(), *VD->evaluateValue(), @@ -2316,10 +2324,11 @@ // FIXME: Eventually we will want to emit vector element references. // Should we be using the alignment of the constant pointer we emitted? - CharUnits Alignment = getNaturalTypeAlignment(E->getType(), nullptr, - /*pointee*/ true); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - return MakeAddrLValue(Address(Val, Alignment), T, BaseInfo); + CharUnits Alignment = getNaturalTypeAlignment(E->getType(), + /* BaseInfo= */ nullptr, + /* TBAAInfo= */ nullptr, + /* forPointeeType= */ true); + return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl); } // Check for captured variables. @@ -2340,13 +2349,13 @@ bool MayAlias = CapLVal.getBaseInfo().getMayAlias(); return MakeAddrLValue( Address(CapLVal.getPointer(), getContext().getDeclAlign(VD)), - CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl, MayAlias)); + CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl, MayAlias), + CGM.getTBAAAccessInfo(CapLVal.getType())); } assert(isa(CurCodeDecl)); Address addr = GetAddrOfBlockDecl(VD, VD->hasAttr()); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - return MakeAddrLValue(addr, T, BaseInfo); + return MakeAddrLValue(addr, T, AlignmentSource::Decl); } } @@ -2360,8 +2369,7 @@ if (ND->hasAttr()) { const auto *VD = cast(ND); ConstantAddress Aliasee = CGM.GetWeakRefReference(VD); - return MakeAddrLValue(Aliasee, T, - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(Aliasee, T, AlignmentSource::Decl); } if (const auto *VD = dyn_cast(ND)) { @@ -2407,8 +2415,7 @@ if (auto RefTy = VD->getType()->getAs()) { LV = EmitLoadOfReferenceLValue(addr, RefTy); } else { - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - LV = MakeAddrLValue(addr, T, BaseInfo); + LV = MakeAddrLValue(addr, T, AlignmentSource::Decl); } bool isLocalStorage = VD->hasLocalStorage(); @@ -2454,8 +2461,10 @@ assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type"); LValueBaseInfo BaseInfo; - Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo); - LValue LV = MakeAddrLValue(Addr, T, BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo, + &TBAAInfo); + LValue LV = MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); LV.getQuals().setAddressSpace(ExprTy.getAddressSpace()); // We should not generate __weak write barrier on indirect reference @@ -2487,7 +2496,8 @@ (E->getOpcode() == UO_Real ? emitAddrOfRealComponent(LV.getAddress(), LV.getType()) : emitAddrOfImagComponent(LV.getAddress(), LV.getType())); - LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo()); + LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo(), + CGM.getTBAAAccessInfo(T)); ElemLV.getQuals().addQualifiers(LV.getQuals()); return ElemLV; } @@ -2507,14 +2517,12 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E), - E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + E->getType(), AlignmentSource::Decl); } LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E), - E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + E->getType(), AlignmentSource::Decl); } LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { @@ -2526,7 +2534,6 @@ StringRef NameItems[] = { PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName}; std::string GVName = llvm::join(NameItems, NameItems + 2, "."); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); if (auto *BD = dyn_cast(CurCodeDecl)) { std::string Name = SL->getString(); if (!Name.empty()) { @@ -2535,14 +2542,14 @@ if (Discriminator) Name += "_" + Twine(Discriminator + 1).str(); auto C = CGM.GetAddrOfConstantCString(Name, GVName.c_str()); - return MakeAddrLValue(C, E->getType(), BaseInfo); + return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); } else { auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str()); - return MakeAddrLValue(C, E->getType(), BaseInfo); + return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); } } auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName); - return MakeAddrLValue(C, E->getType(), BaseInfo); + return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); } /// Emit a type description suitable for use by a runtime sanitizer library. The @@ -3057,7 +3064,8 @@ } Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E, - LValueBaseInfo *BaseInfo) { + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { assert(E->getType()->isArrayType() && "Array to pointer decay must have array source type!"); @@ -3065,6 +3073,7 @@ LValue LV = EmitLValue(E); Address Addr = LV.getAddress(); if (BaseInfo) *BaseInfo = LV.getBaseInfo(); + if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo(); // If the array type was an incomplete type, we need to make sure // the decay ends up being the right type. @@ -3204,9 +3213,8 @@ LValue LHS = EmitLValue(E->getBase()); auto *Idx = EmitIdxAfterBase(/*Promote*/false); assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); - return LValue::MakeVectorElt(LHS.getAddress(), Idx, - E->getBase()->getType(), - LHS.getBaseInfo()); + return LValue::MakeVectorElt(LHS.getAddress(), Idx, E->getBase()->getType(), + LHS.getBaseInfo(), TBAAAccessInfo()); } // All the other cases basically behave like simple offsetting. @@ -3220,17 +3228,19 @@ QualType EltType = LV.getType()->castAs()->getElementType(); Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true, SignedIndices, E->getExprLoc()); - return MakeAddrLValue(Addr, EltType, LV.getBaseInfo()); + return MakeAddrLValue(Addr, EltType, LV.getBaseInfo(), + CGM.getTBAAAccessInfo(EltType)); } LValueBaseInfo BaseInfo; + TBAAAccessInfo TBAAInfo; Address Addr = Address::invalid(); if (const VariableArrayType *vla = getContext().getAsVariableArrayType(E->getType())) { // The base must be a pointer, which is not an aggregate. Emit // it. It needs to be emitted first in case it's what captures // the VLA bounds. - Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); + Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); // The element count here is the total number of non-VLA elements. @@ -3254,7 +3264,7 @@ // Indexing over an interface, as in "NSString *P; P[4];" // Emit the base pointer. - Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); + Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT); @@ -3302,18 +3312,17 @@ E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); + TBAAInfo = CGM.getTBAAAccessInfo(E->getType()); } else { // The base must be a pointer; emit it with an estimate of its alignment. - Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); + Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, E->getExprLoc()); } - LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo); - - // TODO: Preserve/extend path TBAA metadata? + LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo, TBAAInfo); if (getLangOpts().ObjC1 && getLangOpts().getGC() != LangOptions::NonGC) { @@ -3325,6 +3334,7 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, LValueBaseInfo &BaseInfo, + TBAAAccessInfo &TBAAInfo, QualType BaseTy, QualType ElTy, bool IsLowerBound) { LValue BaseLVal; @@ -3356,17 +3366,12 @@ BaseInfo.mergeForCast(TypeInfo); return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), Align); } - return CGF.EmitPointerWithAlignment(Base, &BaseInfo); + return CGF.EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); } LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, bool IsLowerBound) { - QualType BaseTy; - if (auto *ASE = - dyn_cast(E->getBase()->IgnoreParenImpCasts())) - BaseTy = OMPArraySectionExpr::getBaseOriginalType(ASE); - else - BaseTy = E->getBase()->getType(); + QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(E->getBase()); QualType ResultExprTy; if (auto *AT = getContext().getAsArrayType(BaseTy)) ResultExprTy = AT->getElementType(); @@ -3461,13 +3466,14 @@ Address EltPtr = Address::invalid(); LValueBaseInfo BaseInfo; + TBAAAccessInfo TBAAInfo; if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) { // The base must be a pointer, which is not an aggregate. Emit // it. It needs to be emitted first in case it's what captures // the VLA bounds. Address Base = - emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy, - VLA->getElementType(), IsLowerBound); + emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, + BaseTy, VLA->getElementType(), IsLowerBound); // The element count here is the total number of non-VLA elements. llvm::Value *NumElements = getVLASize(VLA).first; @@ -3503,15 +3509,17 @@ ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*SignedIndices=*/false, E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); + TBAAInfo = CGM.getTBAAAccessInfo(ResultExprTy); } else { Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, - BaseTy, ResultExprTy, IsLowerBound); + TBAAInfo, BaseTy, ResultExprTy, + IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*SignedIndices=*/false, E->getExprLoc()); } - return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo); + return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo, TBAAInfo); } LValue CodeGenFunction:: @@ -3524,9 +3532,10 @@ // If it is a pointer to a vector, emit the address and form an lvalue with // it. LValueBaseInfo BaseInfo; - Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo); const PointerType *PT = E->getBase()->getType()->getAs(); - Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo); + Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo, TBAAInfo); Base.getQuals().removeObjCGCAttr(); } else if (E->getBase()->isGLValue()) { // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), @@ -3543,7 +3552,7 @@ Address VecMem = CreateMemTemp(E->getBase()->getType()); Builder.CreateStore(Vec, VecMem); Base = MakeAddrLValue(VecMem, E->getBase()->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + AlignmentSource::Decl); } QualType type = @@ -3557,7 +3566,7 @@ llvm::Constant *CV = llvm::ConstantDataVector::get(getLLVMContext(), Indices); return LValue::MakeExtVectorElt(Base.getAddress(), CV, type, - Base.getBaseInfo()); + Base.getBaseInfo(), TBAAAccessInfo()); } assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); @@ -3568,7 +3577,7 @@ CElts.push_back(BaseElts->getAggregateElement(Indices[i])); llvm::Constant *CV = llvm::ConstantVector::get(CElts); return LValue::MakeExtVectorElt(Base.getExtVectorAddress(), CV, type, - Base.getBaseInfo()); + Base.getBaseInfo(), TBAAAccessInfo()); } LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { @@ -3582,7 +3591,8 @@ LValue BaseLV; if (E->isArrow()) { LValueBaseInfo BaseInfo; - Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); QualType PtrTy = BaseExpr->getType()->getPointeeType(); SanitizerSet SkippedChecks; bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr); @@ -3592,7 +3602,7 @@ SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); - BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo); + BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess); @@ -3669,15 +3679,6 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field) { LValueBaseInfo BaseInfo = base.getBaseInfo(); - AlignmentSource fieldAlignSource = - getFieldAlignmentSource(BaseInfo.getAlignmentSource()); - LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias()); - - QualType type = field->getType(); - const RecordDecl *rec = field->getParent(); - if (rec->isUnion() || rec->hasAttr() || type->isVectorType()) - FieldBaseInfo.setMayAlias(true); - bool mayAlias = FieldBaseInfo.getMayAlias(); if (field->isBitField()) { const CGRecordLayout &RL = @@ -3697,19 +3698,55 @@ QualType fieldType = field->getType().withCVRQualifiers(base.getVRQualifiers()); - return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo); + // TODO: Support TBAA for bit fields. + LValueBaseInfo FieldBaseInfo(BaseInfo.getAlignmentSource(), false); + return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo, + TBAAAccessInfo()); + } + + // Fields of may-alias structures are may-alias themselves. + // FIXME: this should get propagated down through anonymous structs + // and unions. + QualType FieldType = field->getType(); + const RecordDecl *rec = field->getParent(); + AlignmentSource BaseAlignSource = BaseInfo.getAlignmentSource(); + LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(BaseAlignSource), false); + TBAAAccessInfo FieldTBAAInfo; + if (BaseInfo.getMayAlias() || rec->hasAttr() || + FieldType->isVectorType()) { + FieldBaseInfo.setMayAlias(true); + FieldTBAAInfo = CGM.getTBAAMayAliasAccessInfo(); + } else if (rec->isUnion()) { + // TODO: Support TBAA for unions. + FieldBaseInfo.setMayAlias(true); + FieldTBAAInfo = CGM.getTBAAMayAliasAccessInfo(); + } else { + // If no base type been assigned for the base access, then try to generate + // one for this base lvalue. + FieldTBAAInfo = base.getTBAAInfo(); + if (!FieldTBAAInfo.BaseType) { + FieldTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType()); + assert(!FieldTBAAInfo.Offset && + "Nonzero offset for an access with no base type!"); + } + + // Adjust offset to be relative to the base type. + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(field->getParent()); + unsigned CharWidth = getContext().getCharWidth(); + if (FieldTBAAInfo.BaseType) + FieldTBAAInfo.Offset += + Layout.getFieldOffset(field->getFieldIndex()) / CharWidth; + + // Update the final access type. + FieldTBAAInfo.AccessType = CGM.getTBAATypeInfo(FieldType); } Address addr = base.getAddress(); unsigned cvr = base.getVRQualifiers(); - bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; if (rec->isUnion()) { // For unions, there is no pointer adjustment. - assert(!type->isReferenceType() && "union has reference member"); - // TODO: handle path-aware TBAA for union. - TBAAPath = false; - - const auto FieldType = field->getType(); + assert(!FieldType->isReferenceType() && "union has reference member"); if (CGM.getCodeGenOpts().StrictVTablePointers && hasAnyVptr(FieldType, getContext())) // Because unions can easily skip invariant.barriers, we need to add @@ -3721,26 +3758,17 @@ addr = emitAddrOfFieldStorage(*this, addr, field); // If this is a reference field, load the reference right now. - if (const ReferenceType *refType = type->getAs()) { + if (const ReferenceType *refType = FieldType->getAs()) { llvm::LoadInst *load = Builder.CreateLoad(addr, "ref"); if (cvr & Qualifiers::Volatile) load->setVolatile(true); - // Loading the reference will disable path-aware TBAA. - TBAAPath = false; - if (CGM.shouldUseTBAA()) { - llvm::MDNode *tbaa = mayAlias ? CGM.getTBAAMayAliasTypeInfo() : - CGM.getTBAATypeInfo(type); - if (tbaa) - CGM.DecorateInstructionWithTBAA(load, tbaa); - } - - mayAlias = false; - type = refType->getPointeeType(); + CGM.DecorateInstructionWithTBAA(load, FieldTBAAInfo); - CharUnits alignment = - getNaturalTypeAlignment(type, &FieldBaseInfo, /*pointee*/ true); - FieldBaseInfo.setMayAlias(false); - addr = Address(load, alignment); + FieldType = refType->getPointeeType(); + CharUnits Align = getNaturalTypeAlignment(FieldType, &FieldBaseInfo, + &FieldTBAAInfo, + /* forPointeeType= */ true); + addr = Address(load, Align); // Qualifiers on the struct don't apply to the referencee, and // we'll pick up CVR from the actual type later, so reset these @@ -3753,39 +3781,19 @@ // for both unions and structs. A union needs a bitcast, a struct element // will need a bitcast if the LLVM type laid out doesn't match the desired // type. - addr = Builder.CreateElementBitCast(addr, - CGM.getTypes().ConvertTypeForMem(type), - field->getName()); + addr = Builder.CreateElementBitCast( + addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName()); if (field->hasAttr()) addr = EmitFieldAnnotations(field, addr); - LValue LV = MakeAddrLValue(addr, type, FieldBaseInfo); + LValue LV = MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo); LV.getQuals().addCVRQualifiers(cvr); - if (TBAAPath) { - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(field->getParent()); - // Set the base type to be the base type of the base LValue and - // update offset to be relative to the base type. - unsigned CharWidth = getContext().getCharWidth(); - TBAAAccessInfo TBAAInfo = mayAlias ? - TBAAAccessInfo(CGM.getTBAAMayAliasTypeInfo()) : - TBAAAccessInfo(base.getTBAAInfo().BaseType, CGM.getTBAATypeInfo(type), - base.getTBAAInfo().Offset + Layout.getFieldOffset( - field->getFieldIndex()) / CharWidth); - LV.setTBAAInfo(TBAAInfo); - } // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) LV.getQuals().removeObjCGCAttr(); - // Fields of may_alias structs act like 'char' for TBAA purposes. - // FIXME: this should get propagated down through anonymous structs - // and unions. - if (mayAlias && LV.getTBAAAccessType()) - LV.setTBAAAccessType(CGM.getTBAAMayAliasTypeInfo()); - return LV; } @@ -3808,14 +3816,14 @@ LValueBaseInfo FieldBaseInfo( getFieldAlignmentSource(BaseInfo.getAlignmentSource()), BaseInfo.getMayAlias()); - return MakeAddrLValue(V, FieldType, FieldBaseInfo); + return MakeAddrLValue(V, FieldType, FieldBaseInfo, + CGM.getTBAAAccessInfo(FieldType)); } LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){ - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); if (E->isFileScope()) { ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E); - return MakeAddrLValue(GlobalPtr, E->getType(), BaseInfo); + return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl); } if (E->getType()->isVariablyModifiedType()) // make sure to emit the VLA size. @@ -3823,7 +3831,7 @@ Address DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral"); const Expr *InitExpr = E->getInitializer(); - LValue Result = MakeAddrLValue(DeclPtr, E->getType(), BaseInfo); + LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl); EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(), /*Init*/ true); @@ -3925,7 +3933,8 @@ bool MayAlias = lhs->getBaseInfo().getMayAlias() || rhs->getBaseInfo().getMayAlias(); return MakeAddrLValue(result, expr->getType(), - LValueBaseInfo(alignSource, MayAlias)); + LValueBaseInfo(alignSource, MayAlias), + CGM.getTBAAAccessInfo(expr->getType())); } else { assert((lhs || rhs) && "both operands of glvalue conditional are throw-expressions?"); @@ -4023,7 +4032,8 @@ This, DerivedClassDecl, E->path_begin(), E->path_end(), /*NullCheckValue=*/false, E->getExprLoc()); - return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo()); + return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo(), + CGM.getTBAAAccessInfo(E->getType())); } case CK_ToUnion: return EmitAggExprToLValue(E); @@ -4050,7 +4060,8 @@ /*MayBeNull=*/false, CFITCK_DerivedCast, E->getLocStart()); - return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo()); + return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo(), + CGM.getTBAAAccessInfo(E->getType())); } case CK_LValueBitCast: { // This must be a reinterpret_cast (or c-style equivalent). @@ -4066,13 +4077,15 @@ /*MayBeNull=*/false, CFITCK_UnrelatedCast, E->getLocStart()); - return MakeAddrLValue(V, E->getType(), LV.getBaseInfo()); + return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), + CGM.getTBAAAccessInfo(E->getType())); } case CK_ObjCObjectLValueCast: { LValue LV = EmitLValue(E->getSubExpr()); Address V = Builder.CreateElementBitCast(LV.getAddress(), ConvertType(E->getType())); - return MakeAddrLValue(V, E->getType(), LV.getBaseInfo()); + return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), + CGM.getTBAAAccessInfo(E->getType())); } case CK_ZeroToOCLQueue: llvm_unreachable("NULL to OpenCL queue lvalue cast is not valid"); @@ -4261,7 +4274,7 @@ if (!RV.isScalar()) return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + AlignmentSource::Decl); assert(E->getCallReturnType(getContext())->isReferenceType() && "Can't have a scalar return unless the return type is a " @@ -4280,8 +4293,7 @@ && "binding l-value to type which needs a temporary"); AggValueSlot Slot = CreateAggTemp(E->getType()); EmitCXXConstructExpr(E, Slot); - return MakeAddrLValue(Slot.getAddress(), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); } LValue @@ -4296,7 +4308,7 @@ LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) { return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + AlignmentSource::Decl); } LValue @@ -4305,16 +4317,14 @@ Slot.setExternallyDestructed(); EmitAggExpr(E->getSubExpr(), Slot); EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddress()); - return MakeAddrLValue(Slot.getAddress(), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); } LValue CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) { AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue"); EmitLambdaExpr(E, Slot); - return MakeAddrLValue(Slot.getAddress(), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); } LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { @@ -4322,7 +4332,7 @@ if (!RV.isScalar()) return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + AlignmentSource::Decl); assert(E->getMethodDecl()->getReturnType()->isReferenceType() && "Can't have a scalar return unless the return type is a " @@ -4334,8 +4344,7 @@ LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) { Address V = CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector()); - return MakeAddrLValue(V, E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl); } llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface, @@ -4379,7 +4388,7 @@ // Can only get l-value for message expression returning aggregate type RValue RV = EmitAnyExprToTemp(E); return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + AlignmentSource::Decl); } RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee, @@ -4571,10 +4580,12 @@ = E->getRHS()->getType()->getAs(); LValueBaseInfo BaseInfo; + TBAAAccessInfo TBAAInfo; Address MemberAddr = - EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo); + EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo, + &TBAAInfo); - return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo); + return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo, TBAAInfo); } /// Given the address of a temporary variable, produce an r-value of @@ -4582,8 +4593,7 @@ RValue CodeGenFunction::convertTempToRValue(Address addr, QualType type, SourceLocation loc) { - LValue lvalue = MakeAddrLValue(addr, type, - LValueBaseInfo(AlignmentSource::Decl, false)); + LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl); switch (getEvaluationKind(type)) { case TEK_Complex: return RValue::getComplex(EmitLoadOfComplex(lvalue, loc)); @@ -4638,9 +4648,8 @@ if (ov == resultExpr && ov->isRValue() && !forLValue && CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) { CGF.EmitAggExpr(ov->getSourceExpr(), slot); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(), - BaseInfo); + AlignmentSource::Decl); opaqueData = OVMA::bind(CGF, ov, LV); result.RV = slot.asRValue(); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprCXX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1311,29 +1311,44 @@ llvm_unreachable("predeclared global operator new/delete is missing"); } -static std::pair -shouldPassSizeAndAlignToUsualDelete(const FunctionProtoType *FPT) { +namespace { +/// The parameters to pass to a usual operator delete. +struct UsualDeleteParams { + bool DestroyingDelete = false; + bool Size = false; + bool Alignment = false; +}; +} + +static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD) { + UsualDeleteParams Params; + + const FunctionProtoType *FPT = FD->getType()->castAs(); auto AI = FPT->param_type_begin(), AE = FPT->param_type_end(); // The first argument is always a void*. ++AI; - // Figure out what other parameters we should be implicitly passing. - bool PassSize = false; - bool PassAlignment = false; + // The next parameter may be a std::destroying_delete_t. + if (FD->isDestroyingOperatorDelete()) { + Params.DestroyingDelete = true; + assert(AI != AE); + ++AI; + } + // Figure out what other parameters we should be implicitly passing. if (AI != AE && (*AI)->isIntegerType()) { - PassSize = true; + Params.Size = true; ++AI; } if (AI != AE && (*AI)->isAlignValT()) { - PassAlignment = true; + Params.Alignment = true; ++AI; } assert(AI == AE && "unexpected usual deallocation function parameter"); - return {PassSize, PassAlignment}; + return Params; } namespace { @@ -1386,25 +1401,27 @@ OperatorDelete->getType()->getAs(); CallArgList DeleteArgs; - // The first argument is always a void*. + // The first argument is always a void* (or C* for a destroying operator + // delete for class type C). DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(0)); // Figure out what other parameters we should be implicitly passing. - bool PassSize = false; - bool PassAlignment = false; + UsualDeleteParams Params; if (NumPlacementArgs) { // A placement deallocation function is implicitly passed an alignment // if the placement allocation function was, but is never passed a size. - PassAlignment = PassAlignmentToPlacementDelete; + Params.Alignment = PassAlignmentToPlacementDelete; } else { // For a non-placement new-expression, 'operator delete' can take a // size and/or an alignment if it has the right parameters. - std::tie(PassSize, PassAlignment) = - shouldPassSizeAndAlignToUsualDelete(FPT); + Params = getUsualDeleteParams(OperatorDelete); } + assert(!Params.DestroyingDelete && + "should not call destroying delete in a new-expression"); + // The second argument can be a std::size_t (for non-placement delete). - if (PassSize) + if (Params.Size) DeleteArgs.add(Traits::get(CGF, AllocSize), CGF.getContext().getSizeType()); @@ -1412,7 +1429,7 @@ // is an enum whose underlying type is std::size_t. // FIXME: Use the right type as the parameter type. Note that in a call // to operator delete(size_t, ...), we may not have it available. - if (PassAlignment) + if (Params.Alignment) DeleteArgs.add(RValue::get(llvm::ConstantInt::get( CGF.SizeTy, AllocAlign.getQuantity())), CGF.getContext().getSizeType()); @@ -1715,9 +1732,7 @@ CallArgList DeleteArgs; - std::pair PassSizeAndAlign = - shouldPassSizeAndAlignToUsualDelete(DeleteFTy); - + auto Params = getUsualDeleteParams(DeleteFD); auto ParamTypeIt = DeleteFTy->param_type_begin(); // Pass the pointer itself. @@ -1725,8 +1740,16 @@ llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); DeleteArgs.add(RValue::get(DeletePtr), ArgTy); + // Pass the std::destroying_delete tag if present. + if (Params.DestroyingDelete) { + QualType DDTag = *ParamTypeIt++; + // Just pass an 'undef'. We expect the tag type to be an empty struct. + auto *V = llvm::UndefValue::get(getTypes().ConvertType(DDTag)); + DeleteArgs.add(RValue::get(V), DDTag); + } + // Pass the size if the delete function has a size_t parameter. - if (PassSizeAndAlign.first) { + if (Params.Size) { QualType SizeType = *ParamTypeIt++; CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy); llvm::Value *Size = llvm::ConstantInt::get(ConvertType(SizeType), @@ -1745,7 +1768,7 @@ } // Pass the alignment if the delete function has an align_val_t parameter. - if (PassSizeAndAlign.second) { + if (Params.Alignment) { QualType AlignValType = *ParamTypeIt++; CharUnits DeleteTypeAlign = getContext().toCharUnitsFromBits( getContext().getTypeAlignIfKnown(DeleteTy)); @@ -1787,6 +1810,21 @@ OperatorDelete, ElementType); } +/// Emit the code for deleting a single object with a destroying operator +/// delete. If the element type has a non-virtual destructor, Ptr has already +/// been converted to the type of the parameter of 'operator delete'. Otherwise +/// Ptr points to an object of the static type. +static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, Address Ptr, + QualType ElementType) { + auto *Dtor = ElementType->getAsCXXRecordDecl()->getDestructor(); + if (Dtor && Dtor->isVirtual()) + CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, + Dtor); + else + CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); +} + /// Emit the code for deleting a single object. static void EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, @@ -1801,6 +1839,9 @@ DE->getExprLoc(), Ptr.getPointer(), ElementType); + const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); + assert(!OperatorDelete->isDestroyingOperatorDelete()); + // Find the destructor for the type, if applicable. If the // destructor is virtual, we'll just emit the vcall and return. const CXXDestructorDecl *Dtor = nullptr; @@ -1820,7 +1861,6 @@ // Make sure that we call delete even if the dtor throws. // This doesn't have to a conditional cleanup because we're going // to pop it off in a second. - const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); CGF.EHStack.pushCleanup(NormalAndEHCleanup, Ptr.getPointer(), OperatorDelete, ElementType); @@ -1932,10 +1972,19 @@ Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); + QualType DeleteTy = E->getDestroyedType(); + + // A destroying operator delete overrides the entire operation of the + // delete expression. + if (E->getOperatorDelete()->isDestroyingOperatorDelete()) { + EmitDestroyingObjectDelete(*this, E, Ptr, DeleteTy); + EmitBlock(DeleteEnd); + return; + } + // We might be deleting a pointer to array. If so, GEP down to the // first non-array element. // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*) - QualType DeleteTy = Arg->getType()->getAs()->getPointeeType(); if (DeleteTy->isConstantArrayType()) { llvm::Value *Zero = Builder.getInt32(0); SmallVector GEP; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprScalar.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprScalar.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGExprScalar.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGExprScalar.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -3214,6 +3214,16 @@ Value *CR6Param = Builder.getInt32(CR6); llvm::Function *F = CGF.CGM.getIntrinsic(ID); Result = Builder.CreateCall(F, {CR6Param, FirstVecArg, SecondVecArg}); + + // The result type of intrinsic may not be same as E->getType(). + // If E->getType() is not BoolTy, EmitScalarConversion will do the + // conversion work. If E->getType() is BoolTy, EmitScalarConversion will + // do nothing, if ResultTy is not i1 at the same time, it will cause + // crash later. + llvm::IntegerType *ResultTy = cast(Result->getType()); + if (ResultTy->getBitWidth() > 1 && + E->getType() == CGF.getContext().BoolTy) + Result = Builder.CreateTrunc(Result, Builder.getInt1Ty()); return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType(), E->getExprLoc()); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGObjC.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGObjC.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGObjC.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGObjC.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -162,7 +162,7 @@ const Expr *Rhs = ALE->getElement(i); LValue LV = MakeAddrLValue( Builder.CreateConstArrayGEP(Objects, i, getPointerSize()), - ElementType, LValueBaseInfo(AlignmentSource::Decl, false)); + ElementType, AlignmentSource::Decl); llvm::Value *value = EmitScalarExpr(Rhs); EmitStoreThroughLValue(RValue::get(value), LV, true); @@ -174,7 +174,7 @@ const Expr *Key = DLE->getKeyValueElement(i).Key; LValue KeyLV = MakeAddrLValue( Builder.CreateConstArrayGEP(Keys, i, getPointerSize()), - ElementType, LValueBaseInfo(AlignmentSource::Decl, false)); + ElementType, AlignmentSource::Decl); llvm::Value *keyValue = EmitScalarExpr(Key); EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true); @@ -182,7 +182,7 @@ const Expr *Value = DLE->getKeyValueElement(i).Value; LValue ValueLV = MakeAddrLValue( Builder.CreateConstArrayGEP(Objects, i, getPointerSize()), - ElementType, LValueBaseInfo(AlignmentSource::Decl, false)); + ElementType, AlignmentSource::Decl); llvm::Value *valueValue = EmitScalarExpr(Value); EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true); if (TrackNeededObjects) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGObjCRuntime.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGObjCRuntime.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGObjCRuntime.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGObjCRuntime.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -110,7 +110,8 @@ llvm::Type::getIntNTy(CGF.getLLVMContext(), Info->StorageSize)); return LValue::MakeBitfield(Addr, *Info, IvarTy, - LValueBaseInfo(AlignmentSource::Decl, false)); + LValueBaseInfo(AlignmentSource::Decl, false), + TBAAAccessInfo()); } namespace { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenCLRuntime.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenCLRuntime.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenCLRuntime.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenCLRuntime.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -16,6 +16,7 @@ #include "CGOpenCLRuntime.h" #include "CodeGenFunction.h" #include "TargetInfo.h" +#include "clang/CodeGen/ConstantInitBuilder.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalValue.h" #include @@ -103,3 +104,45 @@ .getQuantity(); return llvm::ConstantInt::get(Int32Ty, TypeSize, false); } + +llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() { + assert(CGM.getLangOpts().OpenCL); + return llvm::IntegerType::getInt8PtrTy( + CGM.getLLVMContext(), + CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic)); +} + +CGOpenCLRuntime::EnqueuedBlockInfo +CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) { + // The block literal may be assigned to a const variable. Chasing down + // to get the block literal. + if (auto DR = dyn_cast(E)) { + E = cast(DR->getDecl())->getInit(); + } + if (auto Cast = dyn_cast(E)) { + E = Cast->getSubExpr(); + } + auto *Block = cast(E); + + // The same block literal may be enqueued multiple times. Cache it if + // possible. + auto Loc = EnqueuedBlockMap.find(Block); + if (Loc != EnqueuedBlockMap.end()) { + return Loc->second; + } + + // Emit block literal as a common block expression and get the block invoke + // function. + llvm::Function *Invoke; + auto *V = CGF.EmitBlockLiteral(cast(Block), &Invoke); + auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel( + CGF, Invoke, V->stripPointerCasts()); + + // The common part of the post-processing of the kernel goes here. + F->addFnAttr(llvm::Attribute::NoUnwind); + F->setCallingConv( + CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel)); + EnqueuedBlockInfo Info{F, V}; + EnqueuedBlockMap[Block] = Info; + return Info; +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenCLRuntime.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenCLRuntime.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenCLRuntime.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenCLRuntime.h 2017-10-17 14:41:55.000000000 +0000 @@ -17,11 +17,13 @@ #define LLVM_CLANG_LIB_CODEGEN_CGOPENCLRUNTIME_H #include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" namespace clang { +class Expr; class VarDecl; namespace CodeGen { @@ -35,6 +37,14 @@ llvm::Type *PipeTy; llvm::PointerType *SamplerTy; + /// Structure for enqueued block information. + struct EnqueuedBlockInfo { + llvm::Function *Kernel; /// Enqueued block kernel. + llvm::Value *BlockArg; /// The first argument to enqueued block kernel. + }; + /// Maps block expression to block information. + llvm::DenseMap EnqueuedBlockMap; + public: CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr), SamplerTy(nullptr) {} @@ -59,6 +69,13 @@ // \brief Returnes a value which indicates the alignment in bytes of the pipe // element. virtual llvm::Value *getPipeElemAlign(const Expr *PipeArg); + + /// \return __generic void* type. + llvm::PointerType *getGenericVoidPointerType(); + + /// \return enqueued block information for enqueued block. + EnqueuedBlockInfo emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, + const Expr *E); }; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenMPRuntime.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenMPRuntime.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenMPRuntime.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -265,6 +265,13 @@ return nullptr; } + /// \brief Get an LValue for the current ThreadID variable. + LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { + if (OuterRegionInfo) + return OuterRegionInfo->getThreadIDVariableLValue(CGF); + llvm_unreachable("No LValue for inlined OpenMP construct"); + } + /// \brief Get the name of the capture helper. StringRef getHelperName() const override { if (auto *OuterRegionInfo = getOldCSI()) @@ -779,7 +786,8 @@ /// \param Init Initial expression of array. /// \param SrcAddr Address of the original array. static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, - QualType Type, const Expr *Init, + QualType Type, bool EmitDeclareReductionInit, + const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr = Address::invalid()) { // Perform element-by-element initialization. @@ -833,7 +841,7 @@ // Emit copy. { CodeGenFunction::RunCleanupsScope InitScope(CGF); - if (DRD && (DRD->getInitializer() || !Init)) { + if (EmitDeclareReductionInit) { emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, SrcElementCurrent, ElementTy); } else @@ -880,8 +888,12 @@ // captured region. auto *PrivateVD = cast(cast(ClausesData[N].Private)->getDecl()); + bool EmitDeclareReductionInit = + DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), - DRD ? ClausesData[N].ReductionOp : PrivateVD->getInit(), + EmitDeclareReductionInit, + EmitDeclareReductionInit ? ClausesData[N].ReductionOp + : PrivateVD->getInit(), DRD, SharedLVal.getAddress()); } @@ -980,7 +992,8 @@ SharedLVal = CGF.MakeAddrLValue( CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), CGF.ConvertTypeForMem(SharedType)), - SharedType, SharedAddresses[N].first.getBaseInfo()); + SharedType, SharedAddresses[N].first.getBaseInfo(), + CGF.CGM.getTBAAAccessInfo(SharedType)); if (isa(ClausesData[N].Ref) || CGF.getContext().getAsArrayType(PrivateVD->getType())) { emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); @@ -1033,7 +1046,8 @@ return CGF.MakeAddrLValue( CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), CGF.ConvertTypeForMem(ElTy)), - BaseLV.getType(), BaseLV.getBaseInfo()); + BaseLV.getType(), BaseLV.getBaseInfo(), + CGF.CGM.getTBAAAccessInfo(BaseLV.getType())); } static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, @@ -1131,7 +1145,7 @@ CodeGenFunction &CGF) { return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), getThreadIDVariable()->getType(), - LValueBaseInfo(AlignmentSource::Decl, false)); + AlignmentSource::Decl); } CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) @@ -4072,7 +4086,8 @@ Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl, - SharedRefLValue.getBaseInfo().getMayAlias())); + SharedRefLValue.getBaseInfo().getMayAlias()), + CGF.CGM.getTBAAAccessInfo(SharedRefLValue.getType())); QualType Type = OriginalVD->getType(); if (Type->isArrayType()) { // Initialize firstprivate array. @@ -4268,9 +4283,20 @@ // Build type kmp_routine_entry_t (if not built yet). emitKmpRoutineEntryT(KmpInt32Ty); // Build type kmp_task_t (if not built yet). - if (KmpTaskTQTy.isNull()) { - KmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( - CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); + if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { + if (SavedKmpTaskloopTQTy.isNull()) { + SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( + CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); + } + KmpTaskTQTy = SavedKmpTaskloopTQTy; + } else { + assert(D.getDirectiveKind() == OMPD_task && + "Expected taskloop or task directive"); + if (SavedKmpTaskTQTy.isNull()) { + SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( + CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); + } + KmpTaskTQTy = SavedKmpTaskTQTy; } auto *KmpTaskTQTyRD = cast(KmpTaskTQTy->getAsTagDecl()); // Build particular struct kmp_task_t for the given task. @@ -6886,9 +6912,6 @@ for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), CE = CS.capture_end(); CI != CE; ++CI, ++RI, ++CV) { - StringRef Name; - QualType Ty; - CurBasePointers.clear(); CurPointers.clear(); CurSizes.clear(); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenMPRuntime.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenMPRuntime.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenMPRuntime.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenMPRuntime.h 2017-10-17 14:41:55.000000000 +0000 @@ -318,6 +318,10 @@ /// deconstructors of firstprivate C++ objects */ /// } kmp_task_t; QualType KmpTaskTQTy; + /// Saved kmp_task_t for task directive. + QualType SavedKmpTaskTQTy; + /// Saved kmp_task_t for taskloop-based directive. + QualType SavedKmpTaskloopTQTy; /// \brief Type typedef struct kmp_depend_info { /// kmp_intptr_t base_addr; /// size_t len; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -2253,7 +2253,7 @@ ArgType = CGM.getContext().getPointerType(PointeeTy); QC.addRestrict(); enum { NVPTX_local_addr = 5 }; - QC.addAddressSpace(NVPTX_local_addr); + QC.addAddressSpace(getLangASFromTargetAS(NVPTX_local_addr)); ArgType = QC.apply(CGM.getContext(), ArgType); return ImplicitParamDecl::Create( CGM.getContext(), /*DC=*/nullptr, NativeParam->getLocation(), @@ -2273,7 +2273,7 @@ const Type *NonQualTy = QC.strip(NativeParamType); QualType NativePointeeTy = cast(NonQualTy)->getPointeeType(); unsigned NativePointeeAddrSpace = - NativePointeeTy.getQualifiers().getAddressSpace(); + CGF.getContext().getTargetAddressSpace(NativePointeeTy); QualType TargetTy = TargetParam->getType(); llvm::Value *TargetAddr = CGF.EmitLoadOfScalar( LocalAddr, /*Volatile=*/false, TargetTy, SourceLocation()); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -403,6 +403,27 @@ } return; } + + // Check if current Field is better as a single field run. When current field + // has legal integer width, and its bitfield offset is naturally aligned, it + // is better to make the bitfield a separate storage component so as it can be + // accessed directly with lower cost. + auto IsBetterAsSingleFieldRun = [&](RecordDecl::field_iterator Field) { + if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses) + return false; + unsigned Width = Field->getBitWidthValue(Context); + if (!DataLayout.isLegalInteger(Width)) + return false; + // Make sure Field is natually aligned if it is treated as an IType integer. + if (getFieldBitOffset(*Field) % + Context.toBits(getAlignment(getIntNType(Width))) != + 0) + return false; + return true; + }; + + // The start field is better as a single field run. + bool StartFieldAsSingleRun = false; for (;;) { // Check to see if we need to start a new run. if (Run == FieldEnd) { @@ -414,17 +435,28 @@ Run = Field; StartBitOffset = getFieldBitOffset(*Field); Tail = StartBitOffset + Field->getBitWidthValue(Context); + StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Run); } ++Field; continue; } - // Add bitfields to the run as long as they qualify. - if (Field != FieldEnd && Field->getBitWidthValue(Context) != 0 && + + // If the start field of a new run is better as a single run, or + // if current field is better as a single run, or + // if current field has zero width bitfield, or + // if the offset of current field is inconsistent with the offset of + // previous field plus its offset, + // skip the block below and go ahead to emit the storage. + // Otherwise, try to add bitfields to the run. + if (!StartFieldAsSingleRun && Field != FieldEnd && + !IsBetterAsSingleFieldRun(Field) && + Field->getBitWidthValue(Context) != 0 && Tail == getFieldBitOffset(*Field)) { Tail += Field->getBitWidthValue(Context); ++Field; continue; } + // We've hit a break-point in the run and need to emit a storage field. llvm::Type *Type = getIntNType(Tail - StartBitOffset); // Add the storage member to the record and set the bitfield info for all of @@ -435,6 +467,7 @@ Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset), MemberInfo::Field, nullptr, *Run)); Run = FieldEnd; + StartFieldAsSingleRun = false; } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGStmtOpenMP.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGStmtOpenMP.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGStmtOpenMP.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGStmtOpenMP.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -392,15 +392,14 @@ continue; } - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); - LValue ArgLVal = - CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(), BaseInfo); + LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(), + AlignmentSource::Decl); if (FD->hasCapturedVLAType()) { if (FO.UIntPtrCastRequired) { ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(), Args[Cnt]->getName(), ArgLVal), - FD->getType(), BaseInfo); + FD->getType(), AlignmentSource::Decl); } auto *ExprArg = CGF.EmitLoadOfLValue(ArgLVal, SourceLocation()).getScalarVal(); @@ -497,14 +496,14 @@ llvm::Function *WrapperF = emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes, WrapperCGF.CXXThisValue, WrapperFO); - LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); llvm::SmallVector 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); + WrapperCGF.MakeAddrLValue(I->second.second, Arg->getType(), + AlignmentSource::Decl); CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation()); } else { auto EI = VLASizes.find(Arg); @@ -512,7 +511,8 @@ CallArg = EI->second.second; else { LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg), - Arg->getType(), BaseInfo); + Arg->getType(), + AlignmentSource::Decl); CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation()); } } @@ -2041,18 +2041,6 @@ }); } -void CodeGenFunction::EmitOMPTeamsDistributeDirective( - const OMPTeamsDistributeDirective &S) { - OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); - CGM.getOpenMPRuntime().emitInlinedDirective( - *this, OMPD_teams_distribute, - [&S](CodeGenFunction &CGF, PrePostActionTy &) { - OMPLoopScope PreInitScope(CGF, S); - CGF.EmitStmt( - cast(S.getAssociatedStmt())->getCapturedStmt()); - }); -} - void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective( const OMPTeamsDistributeSimdDirective &S) { OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); @@ -3847,6 +3835,28 @@ emitCommonOMPTargetDirective(*this, S, CodeGen); } +void CodeGenFunction::EmitOMPTeamsDistributeDirective( + const OMPTeamsDistributeDirective &S) { + + auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { + CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); + }; + + // Emit teams region as a standalone region. + auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, + PrePostActionTy &) { + OMPPrivateScope PrivateScope(CGF); + CGF.EmitOMPReductionClauseInit(S, PrivateScope); + (void)PrivateScope.Privatize(); + CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, + CodeGenDistribute); + CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); + }; + emitCommonOMPTeamsDirective(*this, S, OMPD_teams, CodeGen); + emitPostUpdateForReductionClause(*this, S, + [](CodeGenFunction &) { return nullptr; }); +} + void CodeGenFunction::EmitOMPCancellationPointDirective( const OMPCancellationPointDirective &S) { CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(), @@ -4116,7 +4126,14 @@ void CodeGenFunction::EmitOMPTargetParallelForDirective( const OMPTargetParallelForDirective &S) { - // TODO: codegen for target parallel for. + OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); + CGM.getOpenMPRuntime().emitInlinedDirective( + *this, OMPD_target_parallel_for, + [&S](CodeGenFunction &CGF, PrePostActionTy &) { + OMPLoopScope PreInitScope(CGF, S); + CGF.EmitStmt( + cast(S.getAssociatedStmt())->getCapturedStmt()); + }); } /// Emit a helper variable and return corresponding lvalue. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGValue.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGValue.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CGValue.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CGValue.h 2017-10-17 14:41:55.000000000 +0000 @@ -230,9 +230,8 @@ Expr *BaseIvarExp; private: - void Initialize(QualType Type, Qualifiers Quals, - CharUnits Alignment, LValueBaseInfo BaseInfo, - llvm::MDNode *TBAAAccessType = nullptr) { + void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { assert((!Alignment.isZero() || Type->isIncompleteType()) && "initializing l-value with zero alignment!"); this->Type = Type; @@ -241,7 +240,7 @@ assert(this->Alignment == Alignment.getQuantity() && "Alignment exceeds allowed max!"); this->BaseInfo = BaseInfo; - this->TBAAInfo = TBAAAccessInfo(Type, TBAAAccessType, /* Offset= */ 0); + this->TBAAInfo = TBAAInfo; // Initialize Objective-C flags. this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; @@ -311,13 +310,10 @@ TBAAAccessInfo getTBAAInfo() const { return TBAAInfo; } void setTBAAInfo(TBAAAccessInfo Info) { TBAAInfo = Info; } - llvm::MDNode *getTBAAAccessType() const { return TBAAInfo.AccessType; } - void setTBAAAccessType(llvm::MDNode *N) { TBAAInfo.AccessType = N; } - const Qualifiers &getQuals() const { return Quals; } Qualifiers &getQuals() { return Quals; } - unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + LangAS getAddressSpace() const { return Quals.getAddressSpace(); } CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } @@ -370,10 +366,8 @@ // global register lvalue llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - static LValue MakeAddr(Address address, QualType type, - ASTContext &Context, - LValueBaseInfo BaseInfo, - llvm::MDNode *TBAAAccessType = nullptr) { + static LValue MakeAddr(Address address, QualType type, ASTContext &Context, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { Qualifiers qs = type.getQualifiers(); qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); @@ -381,29 +375,31 @@ R.LVType = Simple; assert(address.getPointer()->getType()->isPointerTy()); R.V = address.getPointer(); - R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAAccessType); + R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); return R; } static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx, - QualType type, LValueBaseInfo BaseInfo) { + QualType type, LValueBaseInfo BaseInfo, + TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = VectorElt; R.V = vecAddress.getPointer(); R.VectorIdx = Idx; R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo); + BaseInfo, TBAAInfo); return R; } static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, - QualType type, LValueBaseInfo BaseInfo) { + QualType type, LValueBaseInfo BaseInfo, + TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = ExtVectorElt; R.V = vecAddress.getPointer(); R.VectorElts = Elts; R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo); + BaseInfo, TBAAInfo); return R; } @@ -413,15 +409,15 @@ /// bit-field refers to. /// \param Info - The information describing how to perform the bit-field /// access. - static LValue MakeBitfield(Address Addr, - const CGBitFieldInfo &Info, - QualType type, - LValueBaseInfo BaseInfo) { + static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info, + QualType type, LValueBaseInfo BaseInfo, + TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = BitField; R.V = Addr.getPointer(); R.BitFieldInfo = &Info; - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo); + R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, + TBAAInfo); return R; } @@ -430,7 +426,8 @@ R.LVType = GlobalReg; R.V = Reg.getPointer(); R.Initialize(type, type.getQualifiers(), Reg.getAlignment(), - LValueBaseInfo(AlignmentSource::Decl, false)); + LValueBaseInfo(AlignmentSource::Decl, false), + TBAAAccessInfo()); return R; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenABITypes.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenABITypes.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenABITypes.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenABITypes.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "clang/CodeGen/CodeGenABITypes.h" +#include "CGRecordLayout.h" #include "CodeGenModule.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Frontend/CodeGenOptions.h" @@ -80,3 +81,9 @@ CodeGen::convertTypeForMemory(CodeGenModule &CGM, QualType T) { return CGM.getTypes().ConvertTypeForMem(T); } + +unsigned CodeGen::getLLVMFieldNumber(CodeGenModule &CGM, + const RecordDecl *RD, + const FieldDecl *FD) { + return CGM.getTypes().getCGRecordLayout(RD).getLLVMFieldNo(FD); +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenAction.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenAction.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenAction.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenAction.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -433,6 +433,8 @@ case llvm::SourceMgr::DK_Note: DiagID = diag::note_fe_inline_asm; break; + case llvm::SourceMgr::DK_Remark: + llvm_unreachable("remarks unexpected"); } // If this problem has clang-level source location information, report the // issue in the source with a note showing the instantiated @@ -631,6 +633,10 @@ void BackendConsumer::OptimizationRemarkHandler( const llvm::DiagnosticInfoOptimizationBase &D) { + // Without hotness information, don't show noisy remarks. + if (D.isVerbose() && !D.getHotness()) + return; + if (D.isPassed()) { // Optimization remarks are active only if the -Rpass flag has a regular // expression that matches the name of the pass name in \p D. @@ -915,6 +921,8 @@ case llvm::SourceMgr::DK_Note: DiagID = diag::note_fe_inline_asm; break; + case llvm::SourceMgr::DK_Remark: + llvm_unreachable("remarks unexpected"); } Diags->Report(DiagID).AddString("cannot compile inline asm"); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenFunction.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenFunction.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenFunction.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenFunction.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -118,14 +118,19 @@ } CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo) { - return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo, - /*forPointee*/ true); + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { + return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo, TBAAInfo, + /* forPointeeType= */ true); } CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo, bool forPointeeType) { + if (TBAAInfo) + *TBAAInfo = CGM.getTBAAAccessInfo(T); + // Honor alignment typedef attributes even on incomplete types. // We also honor them straight for C++ class types, even as pointees; // there's an expressivity gap here. @@ -169,9 +174,10 @@ LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { LValueBaseInfo BaseInfo; - CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo); + TBAAAccessInfo TBAAInfo; + CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); return LValue::MakeAddr(Address(V, Alignment), T, getContext(), BaseInfo, - CGM.getTBAATypeInfo(T)); + TBAAInfo); } /// Given a value of type T* that may not be to a complete object, @@ -179,8 +185,10 @@ LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { LValueBaseInfo BaseInfo; - CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, /*pointee*/ true); - return MakeAddrLValue(Address(V, Align), T, BaseInfo); + TBAAAccessInfo TBAAInfo; + CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, + /* forPointeeType= */ true); + return MakeAddrLValue(Address(V, Align), T, BaseInfo, TBAAInfo); } @@ -517,8 +525,8 @@ // for example in clGetKernelArgInfo() implementation between the address // spaces with targets without unique mapping to the OpenCL address spaces // (basically all single AS CPUs). -static unsigned ArgInfoAddressSpace(unsigned LangAS) { - switch (LangAS) { +static unsigned ArgInfoAddressSpace(LangAS AS) { + switch (AS) { case LangAS::opencl_global: return 1; case LangAS::opencl_constant: return 2; case LangAS::opencl_local: return 3; @@ -781,6 +789,15 @@ return true; } +/// Return the UBSan prologue signature for \p FD if one is available. +static llvm::Constant *getPrologueSignature(CodeGenModule &CGM, + const FunctionDecl *FD) { + if (const auto *MD = dyn_cast(FD)) + if (!MD->isStatic()) + return nullptr; + return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM); +} + void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, @@ -900,8 +917,7 @@ // prologue data. if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) { if (const FunctionDecl *FD = dyn_cast_or_null(D)) { - if (llvm::Constant *PrologueSig = - CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) { llvm::Constant *FTRTTIConst = CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); llvm::Constant *FTRTTIConstEncoded = diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenFunction.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenFunction.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenFunction.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenFunction.h 2017-10-17 14:41:55.000000000 +0000 @@ -76,6 +76,10 @@ class ObjCAtSynchronizedStmt; class ObjCAutoreleasePoolStmt; +namespace analyze_os_log { +class OSLogBufferLayout; +} + namespace CodeGen { class CodeGenTypes; class CGCallee; @@ -1580,7 +1584,14 @@ // Block Bits //===--------------------------------------------------------------------===// - llvm::Value *EmitBlockLiteral(const BlockExpr *); + /// Emit block literal. + /// \return an LLVM value which is a pointer to a struct which contains + /// information about the block, including the block invoke function, the + /// captured variables, etc. + /// \param InvokeF will contain the block invoke function if it is not + /// nullptr. + llvm::Value *EmitBlockLiteral(const BlockExpr *, + llvm::Function **InvokeF = nullptr); static void destroyBlockInfos(CGBlockInfo *info); llvm::Function *GenerateBlockFunction(GlobalDecl GD, @@ -1907,33 +1918,48 @@ //===--------------------------------------------------------------------===// LValue MakeAddrLValue(Address Addr, QualType T, - LValueBaseInfo BaseInfo = - LValueBaseInfo(AlignmentSource::Type)) { - return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, - CGM.getTBAATypeInfo(T)); + AlignmentSource Source = AlignmentSource::Type) { + return LValue::MakeAddr(Addr, T, getContext(), + LValueBaseInfo(Source, false), + CGM.getTBAAAccessInfo(T)); + } + + LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, + TBAAAccessInfo TBAAInfo) { + return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); + } + + LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, + AlignmentSource Source = AlignmentSource::Type) { + return LValue::MakeAddr(Address(V, Alignment), T, getContext(), + LValueBaseInfo(Source, false), + CGM.getTBAAAccessInfo(T)); } LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, - LValueBaseInfo BaseInfo = - LValueBaseInfo(AlignmentSource::Type)) { + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { return LValue::MakeAddr(Address(V, Alignment), T, getContext(), - BaseInfo, CGM.getTBAATypeInfo(T)); + BaseInfo, TBAAInfo); } LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr, bool forPointeeType = false); CharUnits getNaturalPointeeTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); Address EmitLoadOfReference(Address Ref, const ReferenceType *RefTy, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType *RefTy); Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy); /// CreateTempAlloca - This creates an alloca and inserts it into the entry @@ -2896,8 +2922,11 @@ LValue EmitOMPSharedLValue(const Expr *E); private: - /// Helpers for blocks - llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info); + /// Helpers for blocks. Returns invoke function by \p InvokeF if it is not + /// nullptr. It should be called without \p InvokeF if the caller does not + /// need invoke function to be returned. + llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info, + llvm::Function **InvokeF = nullptr); /// Helpers for the OpenMP loop directives. void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false); @@ -3054,9 +3083,16 @@ /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, - LValueBaseInfo BaseInfo = - LValueBaseInfo(AlignmentSource::Type), - TBAAAccessInfo TBAAInfo = TBAAAccessInfo(), + AlignmentSource Source = AlignmentSource::Type, + bool isNontemporal = false) { + return EmitLoadOfScalar(Addr, Volatile, Ty, Loc, + LValueBaseInfo(Source, false), + CGM.getTBAAAccessInfo(Ty), isNontemporal); + } + + llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, + SourceLocation Loc, LValueBaseInfo BaseInfo, + TBAAAccessInfo TBAAInfo, bool isNontemporal = false); /// EmitLoadOfScalar - Load a scalar value from an address, taking @@ -3070,9 +3106,15 @@ /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, - LValueBaseInfo BaseInfo = - LValueBaseInfo(AlignmentSource::Type), - TBAAAccessInfo TBAAInfo = TBAAAccessInfo(), + AlignmentSource Source = AlignmentSource::Type, + bool isInit = false, bool isNontemporal = false) { + EmitStoreOfScalar(Value, Addr, Volatile, Ty, LValueBaseInfo(Source, false), + CGM.getTBAAAccessInfo(Ty), isInit, isNontemporal); + } + + void EmitStoreOfScalar(llvm::Value *Value, Address Addr, + bool Volatile, QualType Ty, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isInit = false, bool isNontemporal = false); /// EmitStoreOfScalar - Store a scalar value to an address, taking @@ -3143,7 +3185,8 @@ RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc); Address EmitArrayToPointerDecay(const Expr *Array, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); class ConstantEmission { llvm::PointerIntPair ValueAndIsReference; @@ -3285,7 +3328,8 @@ Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base, llvm::Value *memberPtr, const MemberPointerType *memberPtrType, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); @@ -3304,6 +3348,13 @@ unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue); + /// Emit IR for __builtin_os_log_format. + RValue emitBuiltinOSLogFormat(const CallExpr &E); + + llvm::Function *generateBuiltinOSLogHelperFunction( + const analyze_os_log::OSLogBufferLayout &Layout, + CharUnits BufferAlignment); + RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue); /// EmitTargetBuiltinExpr - Emit the given builtin call. Returns 0 if the call @@ -3857,7 +3908,8 @@ /// reasonable to just ignore the returned alignment when it isn't from an /// explicit source. Address EmitPointerWithAlignment(const Expr *Addr, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK); @@ -3876,6 +3928,7 @@ llvm::Value *EmitX86CpuIs(StringRef CPUStr); llvm::Value *EmitX86CpuSupports(const CallExpr *E); llvm::Value *EmitX86CpuSupports(ArrayRef FeatureStrs); + llvm::Value *EmitX86CpuInit(); }; /// Helper class with most of the code for saving a value for a diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenModule.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenModule.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenModule.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenModule.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -578,10 +578,14 @@ return TBAA->getTypeInfo(QTy); } -llvm::MDNode *CodeGenModule::getTBAAInfoForVTablePtr() { +TBAAAccessInfo CodeGenModule::getTBAAAccessInfo(QualType AccessType) { + return TBAAAccessInfo(getTBAATypeInfo(AccessType)); +} + +TBAAAccessInfo CodeGenModule::getTBAAVTablePtrAccessInfo() { if (!TBAA) - return nullptr; - return TBAA->getTBAAInfoForVTablePtr(); + return TBAAAccessInfo(); + return TBAA->getVTablePtrAccessInfo(); } llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) { @@ -590,30 +594,35 @@ return TBAA->getTBAAStructInfo(QTy); } -llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(TBAAAccessInfo Info) { +llvm::MDNode *CodeGenModule::getTBAABaseTypeInfo(QualType QTy) { if (!TBAA) return nullptr; - return TBAA->getTBAAStructTagInfo(Info); + return TBAA->getBaseTypeInfo(QTy); } -llvm::MDNode *CodeGenModule::getTBAAMayAliasTypeInfo() { +llvm::MDNode *CodeGenModule::getTBAAAccessTagInfo(TBAAAccessInfo Info) { if (!TBAA) return nullptr; - return TBAA->getMayAliasTypeInfo(); + return TBAA->getAccessTagInfo(Info); +} + +TBAAAccessInfo CodeGenModule::getTBAAMayAliasAccessInfo() { + if (!TBAA) + return TBAAAccessInfo(); + return TBAA->getMayAliasAccessInfo(); +} + +TBAAAccessInfo CodeGenModule::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, + TBAAAccessInfo TargetInfo) { + if (!TBAA) + return TBAAAccessInfo(); + return TBAA->mergeTBAAInfoForCast(SourceInfo, TargetInfo); } -/// Decorate the instruction with a TBAA tag. For both scalar TBAA -/// and struct-path aware TBAA, the tag has the same format: -/// base type, access type and offset. -/// When ConvertTypeToTag is true, we create a tag based on the scalar type. void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst, - llvm::MDNode *TBAAInfo, - bool ConvertTypeToTag) { - if (ConvertTypeToTag && TBAA) - Inst->setMetadata(llvm::LLVMContext::MD_tbaa, - TBAA->getTBAAScalarTagInfo(TBAAInfo)); - else - Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); + TBAAAccessInfo TBAAInfo) { + if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo)) + Inst->setMetadata(llvm::LLVMContext::MD_tbaa, Tag); } void CodeGenModule::DecorateInstructionWithInvariantGroup( @@ -2491,10 +2500,9 @@ } } - auto ExpectedAS = + LangAS ExpectedAS = D ? D->getType().getAddressSpace() - : static_cast(LangOpts.OpenCL ? LangAS::opencl_global - : LangAS::Default); + : (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default); assert(getContext().getTargetAddressSpace(ExpectedAS) == Ty->getPointerAddressSpace()); if (AddrSpace != ExpectedAS) @@ -2633,11 +2641,10 @@ getDataLayout().getTypeStoreSizeInBits(Ty)); } -unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { - unsigned AddrSpace; +LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { + LangAS AddrSpace = LangAS::Default; if (LangOpts.OpenCL) { - AddrSpace = D ? D->getType().getAddressSpace() - : static_cast(LangAS::opencl_global); + AddrSpace = D ? D->getType().getAddressSpace() : LangAS::opencl_global; assert(AddrSpace == LangAS::opencl_global || AddrSpace == LangAS::opencl_constant || AddrSpace == LangAS::opencl_local || @@ -3797,7 +3804,7 @@ !EvalResult.hasSideEffects()) Value = &EvalResult.Val; - unsigned AddrSpace = + LangAS AddrSpace = VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); Optional emitter; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenModule.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenModule.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenModule.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenModule.h 2017-10-17 14:41:55.000000000 +0000 @@ -656,28 +656,40 @@ /// the given type. llvm::MDNode *getTBAATypeInfo(QualType QTy); - llvm::MDNode *getTBAAInfoForVTablePtr(); + /// getTBAAAccessInfo - Get TBAA information that describes an access to + /// an object of the given type. + TBAAAccessInfo getTBAAAccessInfo(QualType AccessType); + + /// getTBAAVTablePtrAccessInfo - Get the TBAA information that describes an + /// access to a virtual table pointer. + TBAAAccessInfo getTBAAVTablePtrAccessInfo(); + llvm::MDNode *getTBAAStructInfo(QualType QTy); - /// Get path-aware TBAA tag for a given memory access. - llvm::MDNode *getTBAAStructTagInfo(TBAAAccessInfo Info); + /// getTBAABaseTypeInfo - Get metadata that describes the given base access + /// type. Return null if the type is not suitable for use in TBAA access tags. + llvm::MDNode *getTBAABaseTypeInfo(QualType QTy); + + /// getTBAAAccessTagInfo - Get TBAA tag for a given memory access. + llvm::MDNode *getTBAAAccessTagInfo(TBAAAccessInfo Info); - /// getTBAAMayAliasTypeInfo - Get TBAA information that represents + /// getTBAAMayAliasAccessInfo - Get TBAA information that represents /// may-alias accesses. - llvm::MDNode *getTBAAMayAliasTypeInfo(); + TBAAAccessInfo getTBAAMayAliasAccessInfo(); + + /// mergeTBAAInfoForCast - Get merged TBAA information for the purposes of + /// type casts. + TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, + TBAAAccessInfo TargetInfo); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); bool isPaddedAtomicType(QualType type); bool isPaddedAtomicType(const AtomicType *type); - /// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag - /// is the same as the type. For struct-path aware TBAA, the tag - /// is different from the type: base type, access type and offset. - /// When ConvertTypeToTag is true, we create a tag based on the scalar type. + /// DecorateInstructionWithTBAA - Decorate the instruction with a TBAA tag. void DecorateInstructionWithTBAA(llvm::Instruction *Inst, - llvm::MDNode *TBAAInfo, - bool ConvertTypeToTag = true); + TBAAAccessInfo TBAAInfo); /// Adds !invariant.barrier !tag to instruction void DecorateInstructionWithInvariantGroup(llvm::Instruction *I, @@ -728,7 +740,7 @@ /// /// For languages without explicit address spaces, if D has default address /// space, target-specific global or constant address space may be returned. - unsigned GetGlobalVarAddressSpace(const VarDecl *D); + LangAS GetGlobalVarAddressSpace(const VarDecl *D); /// Return the llvm::Constant for the address of the given global variable. /// If Ty is non-null and if the global doesn't exist, then it will be created @@ -1138,8 +1150,7 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); - bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, - bool InEveryTU); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); /// Set attributes for a global definition. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTBAA.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTBAA.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTBAA.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTBAA.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -171,8 +171,8 @@ return MetadataCache[Ty] = getChar(); } -llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() { - return createTBAAScalarType("vtable pointer", getRoot()); +TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo() { + return TBAAAccessInfo(createTBAAScalarType("vtable pointer", getRoot())); } bool @@ -211,8 +211,8 @@ /* Otherwise, treat whatever it is as a field. */ uint64_t Offset = BaseOffset; uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity(); - llvm::MDNode *TBAAInfo = MayAlias ? getChar() : getTypeInfo(QTy); - llvm::MDNode *TBAATag = getTBAAScalarTagInfo(TBAAInfo); + llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy); + llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType)); Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag)); return true; } @@ -232,8 +232,8 @@ return StructMetadataCache[Ty] = nullptr; } -/// Check if the given type can be handled by path-aware TBAA. -static bool isTBAAPathStruct(QualType QTy) { +/// Check if the given type is a valid base type to be used in access tags. +static bool isValidBaseType(QualType QTy) { if (const RecordType *TTy = QTy->getAs()) { const RecordDecl *RD = TTy->getDecl()->getDefinition(); if (RD->hasFlexibleArrayMember()) @@ -246,12 +246,12 @@ return false; } -llvm::MDNode * -CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { - const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); - assert(isTBAAPathStruct(QTy)); +llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) { + if (!isValidBaseType(QTy)) + return nullptr; - if (llvm::MDNode *N = StructTypeMetadataCache[Ty]) + const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); + if (llvm::MDNode *N = BaseTypeMetadataCache[Ty]) return N; if (const RecordType *TTy = QTy->getAs()) { @@ -263,13 +263,10 @@ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i, ++idx) { QualType FieldQTy = i->getType(); - llvm::MDNode *FieldNode; - if (isTBAAPathStruct(FieldQTy)) - FieldNode = getTBAAStructTypeInfo(FieldQTy); - else - FieldNode = getTypeInfo(FieldQTy); + llvm::MDNode *FieldNode = isValidBaseType(FieldQTy) ? + getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy); if (!FieldNode) - return StructTypeMetadataCache[Ty] = nullptr; + return BaseTypeMetadataCache[Ty] = nullptr; Fields.push_back(std::make_pair( FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth())); } @@ -283,48 +280,40 @@ OutName = RD->getName(); } // Create the struct type node with a vector of pairs (offset, type). - return StructTypeMetadataCache[Ty] = + return BaseTypeMetadataCache[Ty] = MDHelper.createTBAAStructTypeNode(OutName, Fields); } - return StructMetadataCache[Ty] = nullptr; + return BaseTypeMetadataCache[Ty] = nullptr; } -llvm::MDNode *CodeGenTBAA::getTBAAStructTagInfo(TBAAAccessInfo Info) { +llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) { if (!Info.AccessType) return nullptr; if (!CodeGenOpts.StructPathTBAA) - return getTBAAScalarTagInfo(Info.AccessType); + Info = TBAAAccessInfo(Info.AccessType); - const Type *BTy = Context.getCanonicalType(Info.BaseType).getTypePtr(); - TBAAPathTag PathTag = TBAAPathTag(BTy, Info.AccessType, Info.Offset); - if (llvm::MDNode *N = StructTagMetadataCache[PathTag]) + llvm::MDNode *&N = AccessTagMetadataCache[Info]; + if (N) return N; - llvm::MDNode *BNode = nullptr; - if (isTBAAPathStruct(Info.BaseType)) - BNode = getTBAAStructTypeInfo(Info.BaseType); - if (!BNode) - return StructTagMetadataCache[PathTag] = - MDHelper.createTBAAStructTagNode(Info.AccessType, Info.AccessType, - /* Offset= */ 0); - - return StructTagMetadataCache[PathTag] = - MDHelper.createTBAAStructTagNode(BNode, Info.AccessType, Info.Offset); + if (!Info.BaseType) { + Info.BaseType = Info.AccessType; + assert(!Info.Offset && "Nonzero offset for an access with no base type!"); + } + return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType, + Info.Offset); } -llvm::MDNode * -CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) { - if (!AccessNode) - return nullptr; - if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode]) - return N; - - return ScalarTagMetadataCache[AccessNode] = - MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0); +TBAAAccessInfo CodeGenTBAA::getMayAliasAccessInfo() { + return TBAAAccessInfo(getChar()); } -llvm::MDNode *CodeGenTBAA::getMayAliasTypeInfo() { - return getChar(); +TBAAAccessInfo CodeGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, + TBAAAccessInfo TargetInfo) { + TBAAAccessInfo MayAliasInfo = getMayAliasAccessInfo(); + if (SourceInfo == MayAliasInfo || TargetInfo == MayAliasInfo) + return MayAliasInfo; + return TargetInfo; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTBAA.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTBAA.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTBAA.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTBAA.h 2017-10-17 14:41:55.000000000 +0000 @@ -32,32 +32,31 @@ namespace CodeGen { class CGRecordLayout; -struct TBAAPathTag { - TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O) - : BaseT(B), AccessN(A), Offset(O) {} - const Type *BaseT; - const llvm::MDNode *AccessN; - uint64_t Offset; -}; - // TBAAAccessInfo - Describes a memory access in terms of TBAA. struct TBAAAccessInfo { - TBAAAccessInfo(QualType BaseType, llvm::MDNode *AccessType, uint64_t Offset) + TBAAAccessInfo(llvm::MDNode *BaseType, llvm::MDNode *AccessType, + uint64_t Offset) : BaseType(BaseType), AccessType(AccessType), Offset(Offset) {} explicit TBAAAccessInfo(llvm::MDNode *AccessType) - : TBAAAccessInfo(/* BaseType= */ QualType(), AccessType, /* Offset= */ 0) + : TBAAAccessInfo(/* BaseType= */ nullptr, AccessType, /* Offset= */ 0) {} TBAAAccessInfo() : TBAAAccessInfo(/* AccessType= */ nullptr) {} + bool operator==(const TBAAAccessInfo &Other) const { + return BaseType == Other.BaseType && + AccessType == Other.AccessType && + Offset == Other.Offset; + } + /// BaseType - The base/leading access type. May be null if this access /// descriptor represents an access that is not considered to be an access /// to an aggregate or union member. - QualType BaseType; + llvm::MDNode *BaseType; /// AccessType - The final access type. May be null if there is no TBAA /// information available about this access. @@ -82,12 +81,10 @@ /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing /// them. llvm::DenseMap MetadataCache; - /// This maps clang::Types to a struct node in the type DAG. - llvm::DenseMap StructTypeMetadataCache; - /// This maps TBAAPathTags to a tag node. - llvm::DenseMap StructTagMetadataCache; - /// This maps a scalar type to a scalar tag node. - llvm::DenseMap ScalarTagMetadataCache; + /// This maps clang::Types to a base access type in the type DAG. + llvm::DenseMap BaseTypeMetadataCache; + /// This maps TBAA access descriptors to tag nodes. + llvm::DenseMap AccessTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -127,26 +124,29 @@ /// given type. llvm::MDNode *getTypeInfo(QualType QTy); - /// getTBAAInfoForVTablePtr - Get the TBAA MDNode to be used for a - /// dereference of a vtable pointer. - llvm::MDNode *getTBAAInfoForVTablePtr(); + /// getVTablePtrAccessInfo - Get the TBAA information that describes an + /// access to a virtual table pointer. + TBAAAccessInfo getVTablePtrAccessInfo(); /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of /// the given type. llvm::MDNode *getTBAAStructInfo(QualType QTy); - /// Get the MDNode in the type DAG for given struct type QType. - llvm::MDNode *getTBAAStructTypeInfo(QualType QType); - - /// Get path-aware TBAA tag for a given memory access. - llvm::MDNode *getTBAAStructTagInfo(TBAAAccessInfo Info); + /// getBaseTypeInfo - Get metadata that describes the given base access type. + /// Return null if the type is not suitable for use in TBAA access tags. + llvm::MDNode *getBaseTypeInfo(QualType QTy); - /// Get the scalar tag MDNode for a given scalar type. - llvm::MDNode *getTBAAScalarTagInfo(llvm::MDNode *AccessNode); + /// getAccessTagInfo - Get TBAA tag for a given memory access. + llvm::MDNode *getAccessTagInfo(TBAAAccessInfo Info); - /// getMayAliasTypeInfo - Get TBAA information that represents may-alias + /// getMayAliasAccessInfo - Get TBAA information that represents may-alias /// accesses. - llvm::MDNode *getMayAliasTypeInfo(); + TBAAAccessInfo getMayAliasAccessInfo(); + + /// mergeTBAAInfoForCast - Get merged TBAA information for the purpose of + /// type casts. + TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, + TBAAAccessInfo TargetInfo); }; } // end namespace CodeGen @@ -154,31 +154,31 @@ namespace llvm { -template<> struct DenseMapInfo { - static clang::CodeGen::TBAAPathTag getEmptyKey() { - return clang::CodeGen::TBAAPathTag( - DenseMapInfo::getEmptyKey(), - DenseMapInfo::getEmptyKey(), +template<> struct DenseMapInfo { + static clang::CodeGen::TBAAAccessInfo getEmptyKey() { + return clang::CodeGen::TBAAAccessInfo( + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), DenseMapInfo::getEmptyKey()); } - static clang::CodeGen::TBAAPathTag getTombstoneKey() { - return clang::CodeGen::TBAAPathTag( - DenseMapInfo::getTombstoneKey(), - DenseMapInfo::getTombstoneKey(), + static clang::CodeGen::TBAAAccessInfo getTombstoneKey() { + return clang::CodeGen::TBAAAccessInfo( + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), DenseMapInfo::getTombstoneKey()); } - static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) { - return DenseMapInfo::getHashValue(Val.BaseT) ^ - DenseMapInfo::getHashValue(Val.AccessN) ^ + static unsigned getHashValue(const clang::CodeGen::TBAAAccessInfo &Val) { + return DenseMapInfo::getHashValue(Val.BaseType) ^ + DenseMapInfo::getHashValue(Val.AccessType) ^ DenseMapInfo::getHashValue(Val.Offset); } - static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS, - const clang::CodeGen::TBAAPathTag &RHS) { - return LHS.BaseT == RHS.BaseT && - LHS.AccessN == RHS.AccessN && + static bool isEqual(const clang::CodeGen::TBAAAccessInfo &LHS, + const clang::CodeGen::TBAAAccessInfo &RHS) { + return LHS.BaseType == RHS.BaseType && + LHS.AccessType == RHS.AccessType && LHS.Offset == RHS.Offset; } }; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTypeCache.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTypeCache.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTypeCache.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTypeCache.h 2017-10-17 14:41:55.000000000 +0000 @@ -15,6 +15,7 @@ #define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H #include "clang/AST/CharUnits.h" +#include "clang/Basic/AddressSpaces.h" #include "llvm/IR/CallingConv.h" namespace llvm { @@ -94,7 +95,7 @@ unsigned char SizeAlignInBytes; }; - unsigned ASTAllocaAddressSpace; + LangAS ASTAllocaAddressSpace; CharUnits getSizeSize() const { return CharUnits::fromQuantity(SizeSizeInBytes); @@ -114,7 +115,7 @@ llvm::CallingConv::ID BuiltinCC; llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; } - unsigned getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; } + LangAS getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; } }; } // end namespace CodeGen diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTypes.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTypes.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CodeGenTypes.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CodeGenTypes.h 2017-10-17 14:41:55.000000000 +0000 @@ -164,8 +164,6 @@ llvm::SmallSet RecordsWithOpaqueMemberPointers; - unsigned ClangCallConvToLLVMCallConv(CallingConv CC); - public: CodeGenTypes(CodeGenModule &cgm); ~CodeGenTypes(); @@ -180,6 +178,9 @@ llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); } const CodeGenOptions &getCodeGenOpts() const; + /// Convert clang calling convention to LLVM callilng convention. + unsigned ClangCallConvToLLVMCallConv(CallingConv CC); + /// ConvertType - Convert type T into a llvm::Type. llvm::Type *ConvertType(QualType T); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/ConstantEmitter.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/ConstantEmitter.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/ConstantEmitter.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/ConstantEmitter.h 2017-10-17 14:41:55.000000000 +0000 @@ -40,7 +40,7 @@ /// The AST address space where this (non-abstract) initializer is going. /// Used for generating appropriate placeholders. - unsigned DestAddressSpace; + LangAS DestAddressSpace; llvm::SmallVector, 4> PlaceholderAddresses; @@ -68,11 +68,9 @@ /// Try to emit the initiaizer of the given declaration as an abstract /// constant. If this succeeds, the emission must be finalized. llvm::Constant *tryEmitForInitializer(const VarDecl &D); - llvm::Constant *tryEmitForInitializer(const Expr *E, - unsigned destAddrSpace, + llvm::Constant *tryEmitForInitializer(const Expr *E, LangAS destAddrSpace, QualType destType); - llvm::Constant *emitForInitializer(const APValue &value, - unsigned destAddrSpace, + llvm::Constant *emitForInitializer(const APValue &value, LangAS destAddrSpace, QualType destType); void finalize(llvm::GlobalVariable *global); @@ -151,7 +149,7 @@ llvm::GlobalValue *placeholder); private: - void initializeNonAbstract(unsigned destAS) { + void initializeNonAbstract(LangAS destAS) { assert(!InitializedNonAbstract); InitializedNonAbstract = true; DestAddressSpace = destAS; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CoverageMappingGen.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CoverageMappingGen.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/CoverageMappingGen.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/CoverageMappingGen.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -758,6 +758,22 @@ handleFileExit(getEnd(S)); } + /// Determine whether the final deferred region emitted in \p Body should be + /// discarded. + static bool discardFinalDeferredRegionInDecl(Stmt *Body) { + if (auto *CS = dyn_cast(Body)) { + Stmt *LastStmt = CS->body_back(); + if (auto *IfElse = dyn_cast(LastStmt)) { + if (auto *Else = dyn_cast_or_null(IfElse->getElse())) + LastStmt = Else->body_back(); + else + LastStmt = IfElse->getElse(); + } + return dyn_cast_or_null(LastStmt); + } + return false; + } + void VisitDecl(const Decl *D) { assert(!DeferredRegion && "Deferred region never completed"); @@ -770,14 +786,14 @@ Counter ExitCount = propagateCounts(getRegionCounter(Body), Body); assert(RegionStack.empty() && "Regions entered but never exited"); - // Special case: if the last statement is a return, throw away the - // deferred region. This allows the closing brace to have a count. - if (auto *CS = dyn_cast_or_null(Body)) - if (dyn_cast_or_null(CS->body_back())) + if (DeferredRegion) { + // Complete (or discard) any deferred regions introduced by the last + // statement. + if (discardFinalDeferredRegionInDecl(Body)) DeferredRegion = None; - - // Complete any deferred regions introduced by the last statement. - popRegions(completeDeferred(ExitCount, getEnd(Body))); + else + popRegions(completeDeferred(ExitCount, getEnd(Body))); + } } void VisitReturnStmt(const ReturnStmt *S) { @@ -1083,16 +1099,18 @@ } void VisitBinLAnd(const BinaryOperator *E) { - extendRegion(E); - Visit(E->getLHS()); + extendRegion(E->getLHS()); + propagateCounts(getRegion().getCounter(), E->getLHS()); + handleFileExit(getEnd(E->getLHS())); extendRegion(E->getRHS()); propagateCounts(getRegionCounter(E), E->getRHS()); } void VisitBinLOr(const BinaryOperator *E) { - extendRegion(E); - Visit(E->getLHS()); + extendRegion(E->getLHS()); + propagateCounts(getRegion().getCounter(), E->getLHS()); + handleFileExit(getEnd(E->getLHS())); extendRegion(E->getRHS()); propagateCounts(getRegionCounter(E), E->getRHS()); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/ItaniumCXXABI.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/ItaniumCXXABI.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/ItaniumCXXABI.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/ItaniumCXXABI.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -3664,6 +3664,18 @@ !CGM.TryEmitBaseDestructorAsAlias(DD)) return; + // FIXME: The deleting destructor is equivalent to the selected operator + // delete if: + // * either the delete is a destroying operator delete or the destructor + // would be trivial if it weren't virtual, + // * the conversion from the 'this' parameter to the first parameter of the + // destructor is equivalent to a bitcast, + // * the destructor does not have an implicit "this" return, and + // * the operator delete has the same calling convention and IR function type + // as the destructor. + // In such cases we should try to emit the deleting dtor as an alias to the + // selected 'operator delete'. + llvm::Function *Fn = CGM.codegenCXXStructor(MD, Type); if (CGType == StructorCodegen::COMDAT) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/MicrosoftCXXABI.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/MicrosoftCXXABI.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/MicrosoftCXXABI.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/MicrosoftCXXABI.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -3805,7 +3805,7 @@ if (!dtor->getParent()->getNumVBases() && (dtorType == StructorType::Complete || dtorType == StructorType::Base)) { bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias( - GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base), true); + GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base)); if (ProducedAlias) { if (dtorType == StructorType::Complete) return; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/TargetInfo.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/TargetInfo.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/TargetInfo.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/TargetInfo.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -14,6 +14,7 @@ #include "TargetInfo.h" #include "ABIInfo.h" +#include "CGBlocks.h" #include "CGCXXABI.h" #include "CGValue.h" #include "CodeGenFunction.h" @@ -24,6 +25,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Type.h" #include "llvm/Support/raw_ostream.h" @@ -421,18 +423,17 @@ return llvm::ConstantPointerNull::get(T); } -unsigned TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const { +LangAS TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, + const VarDecl *D) const { assert(!CGM.getLangOpts().OpenCL && !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) && "Address space agnostic languages only"); - return D ? D->getType().getAddressSpace() - : static_cast(LangAS::Default); + return D ? D->getType().getAddressSpace() : LangAS::Default; } llvm::Value *TargetCodeGenInfo::performAddrSpaceCast( - CodeGen::CodeGenFunction &CGF, llvm::Value *Src, unsigned SrcAddr, - unsigned DestAddr, llvm::Type *DestTy, bool isNonNull) const { + CodeGen::CodeGenFunction &CGF, llvm::Value *Src, LangAS SrcAddr, + LangAS DestAddr, llvm::Type *DestTy, bool isNonNull) const { // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. if (auto *C = dyn_cast(Src)) @@ -442,7 +443,7 @@ llvm::Constant * TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *Src, - unsigned SrcAddr, unsigned DestAddr, + LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy) const { // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. @@ -7609,14 +7610,18 @@ llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, llvm::PointerType *T, QualType QT) const override; - unsigned getASTAllocaAddressSpace() const override { - return LangAS::FirstTargetAddressSpace + - getABIInfo().getDataLayout().getAllocaAddrSpace(); + LangAS getASTAllocaAddressSpace() const override { + return getLangASFromTargetAS( + getABIInfo().getDataLayout().getAllocaAddrSpace()); } - unsigned getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const override; + LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, + const VarDecl *D) const override; llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S, llvm::LLVMContext &C) const override; + llvm::Function * + createEnqueuedBlockKernel(CodeGenFunction &CGF, + llvm::Function *BlockInvokeFunc, + llvm::Value *BlockLiteral) const override; }; } @@ -7701,21 +7706,19 @@ llvm::ConstantPointerNull::get(NPT), PT); } -unsigned +LangAS AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, const VarDecl *D) const { assert(!CGM.getLangOpts().OpenCL && !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) && "Address space agnostic languages only"); - unsigned DefaultGlobalAS = - LangAS::FirstTargetAddressSpace + - CGM.getContext().getTargetAddressSpace(LangAS::opencl_global); + LangAS DefaultGlobalAS = getLangASFromTargetAS( + CGM.getContext().getTargetAddressSpace(LangAS::opencl_global)); if (!D) return DefaultGlobalAS; - unsigned AddrSpace = D->getType().getAddressSpace(); - assert(AddrSpace == LangAS::Default || - AddrSpace >= LangAS::FirstTargetAddressSpace); + LangAS AddrSpace = D->getType().getAddressSpace(); + assert(AddrSpace == LangAS::Default || isTargetAddressSpace(AddrSpace)); if (AddrSpace != LangAS::Default) return AddrSpace; @@ -8917,3 +8920,109 @@ return SetCGInfo(new SPIRTargetCodeGenInfo(Types)); } } + +/// Create an OpenCL kernel for an enqueued block. +/// +/// The kernel has the same function type as the block invoke function. Its +/// name is the name of the block invoke function postfixed with "_kernel". +/// It simply calls the block invoke function then returns. +llvm::Function * +TargetCodeGenInfo::createEnqueuedBlockKernel(CodeGenFunction &CGF, + llvm::Function *Invoke, + llvm::Value *BlockLiteral) const { + auto *InvokeFT = Invoke->getFunctionType(); + llvm::SmallVector ArgTys; + for (auto &P : InvokeFT->params()) + ArgTys.push_back(P); + auto &C = CGF.getLLVMContext(); + std::string Name = Invoke->getName().str() + "_kernel"; + auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), ArgTys, false); + auto *F = llvm::Function::Create(FT, llvm::GlobalValue::InternalLinkage, Name, + &CGF.CGM.getModule()); + auto IP = CGF.Builder.saveIP(); + auto *BB = llvm::BasicBlock::Create(C, "entry", F); + auto &Builder = CGF.Builder; + Builder.SetInsertPoint(BB); + llvm::SmallVector Args; + for (auto &A : F->args()) + Args.push_back(&A); + Builder.CreateCall(Invoke, Args); + Builder.CreateRetVoid(); + Builder.restoreIP(IP); + return F; +} + +/// Create an OpenCL kernel for an enqueued block. +/// +/// The type of the first argument (the block literal) is the struct type +/// of the block literal instead of a pointer type. The first argument +/// (block literal) is passed directly by value to the kernel. The kernel +/// allocates the same type of struct on stack and stores the block literal +/// to it and passes its pointer to the block invoke function. The kernel +/// has "enqueued-block" function attribute and kernel argument metadata. +llvm::Function *AMDGPUTargetCodeGenInfo::createEnqueuedBlockKernel( + CodeGenFunction &CGF, llvm::Function *Invoke, + llvm::Value *BlockLiteral) const { + auto &Builder = CGF.Builder; + auto &C = CGF.getLLVMContext(); + + auto *BlockTy = BlockLiteral->getType()->getPointerElementType(); + auto *InvokeFT = Invoke->getFunctionType(); + llvm::SmallVector ArgTys; + llvm::SmallVector AddressQuals; + llvm::SmallVector AccessQuals; + llvm::SmallVector ArgTypeNames; + llvm::SmallVector ArgBaseTypeNames; + llvm::SmallVector ArgTypeQuals; + llvm::SmallVector ArgNames; + + ArgTys.push_back(BlockTy); + ArgTypeNames.push_back(llvm::MDString::get(C, "__block_literal")); + AddressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(0))); + ArgBaseTypeNames.push_back(llvm::MDString::get(C, "__block_literal")); + ArgTypeQuals.push_back(llvm::MDString::get(C, "")); + AccessQuals.push_back(llvm::MDString::get(C, "none")); + ArgNames.push_back(llvm::MDString::get(C, "block_literal")); + for (unsigned I = 1, E = InvokeFT->getNumParams(); I < E; ++I) { + ArgTys.push_back(InvokeFT->getParamType(I)); + ArgTys.push_back(BlockTy); + ArgTypeNames.push_back(llvm::MDString::get(C, "void*")); + AddressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(3))); + AccessQuals.push_back(llvm::MDString::get(C, "none")); + ArgBaseTypeNames.push_back(llvm::MDString::get(C, "void*")); + ArgTypeQuals.push_back(llvm::MDString::get(C, "")); + ArgNames.push_back( + llvm::MDString::get(C, (Twine("local_arg") + Twine(I)).str())); + } + std::string Name = Invoke->getName().str() + "_kernel"; + auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), ArgTys, false); + auto *F = llvm::Function::Create(FT, llvm::GlobalValue::InternalLinkage, Name, + &CGF.CGM.getModule()); + F->addFnAttr("enqueued-block"); + auto IP = CGF.Builder.saveIP(); + auto *BB = llvm::BasicBlock::Create(C, "entry", F); + Builder.SetInsertPoint(BB); + unsigned BlockAlign = CGF.CGM.getDataLayout().getPrefTypeAlignment(BlockTy); + auto *BlockPtr = Builder.CreateAlloca(BlockTy, nullptr); + BlockPtr->setAlignment(BlockAlign); + Builder.CreateAlignedStore(F->arg_begin(), BlockPtr, BlockAlign); + auto *Cast = Builder.CreatePointerCast(BlockPtr, InvokeFT->getParamType(0)); + llvm::SmallVector Args; + Args.push_back(Cast); + for (auto I = F->arg_begin() + 1, E = F->arg_end(); I != E; ++I) + Args.push_back(I); + Builder.CreateCall(Invoke, Args); + Builder.CreateRetVoid(); + Builder.restoreIP(IP); + + F->setMetadata("kernel_arg_addr_space", llvm::MDNode::get(C, AddressQuals)); + F->setMetadata("kernel_arg_access_qual", llvm::MDNode::get(C, AccessQuals)); + F->setMetadata("kernel_arg_type", llvm::MDNode::get(C, ArgTypeNames)); + F->setMetadata("kernel_arg_base_type", + llvm::MDNode::get(C, ArgBaseTypeNames)); + F->setMetadata("kernel_arg_type_qual", llvm::MDNode::get(C, ArgTypeQuals)); + if (CGF.CGM.getCodeGenOpts().EmitOpenCLArgMetadata) + F->setMetadata("kernel_arg_name", llvm::MDNode::get(C, ArgNames)); + + return F; +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/TargetInfo.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/TargetInfo.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/CodeGen/TargetInfo.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/CodeGen/TargetInfo.h 2017-10-17 14:41:55.000000000 +0000 @@ -37,6 +37,7 @@ class ABIInfo; class CallArgList; class CodeGenFunction; +class CGBlockInfo; class CGFunctionInfo; /// TargetCodeGenInfo - This class organizes various target-specific @@ -235,11 +236,11 @@ /// other than OpenCL and CUDA. /// If \p D is nullptr, returns the default target favored address space /// for global variable. - virtual unsigned getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const; + virtual LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, + const VarDecl *D) const; /// Get the AST address space for alloca. - virtual unsigned getASTAllocaAddressSpace() const { return LangAS::Default; } + virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. @@ -248,9 +249,8 @@ /// \param DestTy is the destination LLVM pointer type. /// \param IsNonNull is the flag indicating \p V is known to be non null. virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, - llvm::Value *V, unsigned SrcAddr, - unsigned DestAddr, - llvm::Type *DestTy, + llvm::Value *V, LangAS SrcAddr, + LangAS DestAddr, llvm::Type *DestTy, bool IsNonNull = false) const; /// Perform address space cast of a constant expression of pointer type. @@ -258,13 +258,45 @@ /// \param SrcAddr is the language address space of \p V. /// \param DestAddr is the targeted language address space. /// \param DestTy is the destination LLVM pointer type. - virtual llvm::Constant * - performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *V, unsigned SrcAddr, - unsigned DestAddr, llvm::Type *DestTy) const; + virtual llvm::Constant *performAddrSpaceCast(CodeGenModule &CGM, + llvm::Constant *V, + LangAS SrcAddr, LangAS DestAddr, + llvm::Type *DestTy) const; /// Get the syncscope used in LLVM IR. virtual llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S, llvm::LLVMContext &C) const; + + /// Inteface class for filling custom fields of a block literal for OpenCL. + class TargetOpenCLBlockHelper { + public: + typedef std::pair ValueTy; + TargetOpenCLBlockHelper() {} + virtual ~TargetOpenCLBlockHelper() {} + /// Get the custom field types for OpenCL blocks. + virtual llvm::SmallVector getCustomFieldTypes() = 0; + /// Get the custom field values for OpenCL blocks. + virtual llvm::SmallVector + getCustomFieldValues(CodeGenFunction &CGF, const CGBlockInfo &Info) = 0; + virtual bool areAllCustomFieldValuesConstant(const CGBlockInfo &Info) = 0; + /// Get the custom field values for OpenCL blocks if all values are LLVM + /// constants. + virtual llvm::SmallVector + getCustomFieldValues(CodeGenModule &CGM, const CGBlockInfo &Info) = 0; + }; + virtual TargetOpenCLBlockHelper *getTargetOpenCLBlockHelper() const { + return nullptr; + } + + /// Create an OpenCL kernel for an enqueued block. The kernel function is + /// a wrapper for the block invoke function with target-specific calling + /// convention and ABI as an OpenCL kernel. The wrapper function accepts + /// block context and block arguments in target-specific way and calls + /// the original block invoke function. + virtual llvm::Function * + createEnqueuedBlockKernel(CodeGenFunction &CGF, + llvm::Function *BlockInvokeFunc, + llvm::Value *BlockLiteral) const; }; } // namespace CodeGen diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/Compilation.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/Compilation.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/Compilation.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/Compilation.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -28,7 +28,7 @@ : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u), Args(_Args), TranslatedArgs(_TranslatedArgs), ForDiagnostics(false), ContainsError(ContainsError) { - // The offloading host toolchain is the default tool chain. + // The offloading host toolchain is the default toolchain. OrderedOffloadingToolchains.insert( std::make_pair(Action::OFK_Host, &DefaultToolChain)); } @@ -52,9 +52,15 @@ DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}]; if (!Entry) { SmallVector AllocatedArgs; + DerivedArgList *OpenMPArgs = nullptr; // Translate OpenMP toolchain arguments provided via the -Xopenmp-target flags. - DerivedArgList *OpenMPArgs = TC->TranslateOpenMPTargetArgs( - *TranslatedArgs, DeviceOffloadKind, AllocatedArgs); + if (DeviceOffloadKind == Action::OFK_OpenMP) { + const ToolChain *HostTC = getSingleOffloadToolChain(); + bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple()); + OpenMPArgs = TC->TranslateOpenMPTargetArgs( + *TranslatedArgs, SameTripleAsHost, AllocatedArgs); + } + if (!OpenMPArgs) { Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind); if (!Entry) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/SanitizerArgs.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/SanitizerArgs.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/SanitizerArgs.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/SanitizerArgs.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -171,19 +171,23 @@ } bool SanitizerArgs::needsUbsanRt() const { - return ((Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || - CoverageFeatures) && - !Sanitizers.has(Address) && !Sanitizers.has(Memory) && - !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) && - !Sanitizers.has(Leak) && !CfiCrossDso; + // All of these include ubsan. + if (needsAsanRt() || needsMsanRt() || needsTsanRt() || needsDfsanRt() || + needsLsanRt() || needsCfiDiagRt()) + return false; + + return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || + CoverageFeatures; } bool SanitizerArgs::needsCfiRt() const { - return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso; + return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso && + !ImplicitCfiRuntime; } bool SanitizerArgs::needsCfiDiagRt() const { - return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso; + return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso && + !ImplicitCfiRuntime; } bool SanitizerArgs::requiresPIE() const { @@ -610,10 +614,14 @@ CoverageFeatures |= CoverageFunc; } + SharedRuntime = + Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan, + TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() || + TC.getTriple().isOSDarwin()); + + ImplicitCfiRuntime = TC.getTriple().isAndroid(); + if (AllAddedKinds & Address) { - AsanSharedRuntime = - Args.hasArg(options::OPT_shared_libasan) || - TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia(); NeedPIE |= TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia(); if (Arg *A = Args.getLastArg(options::OPT_fsanitize_address_field_padding)) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChain.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChain.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChain.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChain.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -390,7 +390,11 @@ // then use whatever the default system linker is. return GetProgramPath(getDefaultLinker()); } else { - llvm::SmallString<8> LinkerName("ld."); + llvm::SmallString<8> LinkerName; + if (Triple.isOSDarwin()) + LinkerName.append("ld64."); + else + LinkerName.append("ld."); LinkerName.append(UseLinker); std::string LinkerPath(GetProgramPath(LinkerName.c_str())); @@ -801,74 +805,68 @@ } llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( - const llvm::opt::DerivedArgList &Args, - Action::OffloadKind DeviceOffloadKind, - SmallVector &AllocatedArgs) const { - if (DeviceOffloadKind == Action::OFK_OpenMP) { - DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); - const OptTable &Opts = getDriver().getOpts(); - bool Modified = false; - - // Handle -Xopenmp-target flags - for (Arg *A : Args) { - // Exclude flags which may only apply to the host toolchain. - // Do not exclude flags when the host triple (AuxTriple) - // matches the current toolchain triple. If it is not present - // at all, target and host share a toolchain. - if (A->getOption().matches(options::OPT_m_Group)) { - if (!getAuxTriple() || getAuxTriple()->str() == getTriple().str()) - DAL->append(A); - else - Modified = true; - continue; - } - - unsigned Index; - unsigned Prev; - bool XOpenMPTargetNoTriple = A->getOption().matches( - options::OPT_Xopenmp_target); - - if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) { - // Passing device args: -Xopenmp-target= -opt=val. - if (A->getValue(0) == getTripleString()) - Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); - else - continue; - } else if (XOpenMPTargetNoTriple) { - // Passing device args: -Xopenmp-target -opt=val. - Index = Args.getBaseArgs().MakeIndex(A->getValue(0)); - } else { + const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, + SmallVectorImpl &AllocatedArgs) const { + DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); + const OptTable &Opts = getDriver().getOpts(); + bool Modified = false; + + // Handle -Xopenmp-target flags + for (Arg *A : Args) { + // Exclude flags which may only apply to the host toolchain. + // Do not exclude flags when the host triple (AuxTriple) + // matches the current toolchain triple. If it is not present + // at all, target and host share a toolchain. + if (A->getOption().matches(options::OPT_m_Group)) { + if (SameTripleAsHost) DAL->append(A); - continue; - } + else + Modified = true; + continue; + } - // Parse the argument to -Xopenmp-target. - Prev = Index; - std::unique_ptr XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); - if (!XOpenMPTargetArg || Index > Prev + 1) { - getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) - << A->getAsString(Args); - continue; - } - if (XOpenMPTargetNoTriple && XOpenMPTargetArg && - Args.getAllArgValues( - options::OPT_fopenmp_targets_EQ).size() != 1) { - getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple); + unsigned Index; + unsigned Prev; + bool XOpenMPTargetNoTriple = + A->getOption().matches(options::OPT_Xopenmp_target); + + if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) { + // Passing device args: -Xopenmp-target= -opt=val. + if (A->getValue(0) == getTripleString()) + Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); + else continue; - } - XOpenMPTargetArg->setBaseArg(A); - A = XOpenMPTargetArg.release(); - AllocatedArgs.push_back(A); + } else if (XOpenMPTargetNoTriple) { + // Passing device args: -Xopenmp-target -opt=val. + Index = Args.getBaseArgs().MakeIndex(A->getValue(0)); + } else { DAL->append(A); - Modified = true; + continue; } - if (Modified) { - return DAL; - } else { - delete DAL; + // Parse the argument to -Xopenmp-target. + Prev = Index; + std::unique_ptr XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); + if (!XOpenMPTargetArg || Index > Prev + 1) { + getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) + << A->getAsString(Args); + continue; + } + if (XOpenMPTargetNoTriple && XOpenMPTargetArg && + Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) { + getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple); + continue; } + XOpenMPTargetArg->setBaseArg(A); + A = XOpenMPTargetArg.release(); + AllocatedArgs.push_back(A); + DAL->append(A); + Modified = true; } + if (Modified) + return DAL; + + delete DAL; return nullptr; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Clang.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Clang.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Clang.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Clang.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -273,21 +273,6 @@ OutStrings.push_back(Args.MakeArgString(Out)); } -static void getHexagonTargetFeatures(const ArgList &Args, - std::vector &Features) { - handleTargetFeaturesGroup(Args, Features, - options::OPT_m_hexagon_Features_Group); - - bool UseLongCalls = false; - if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, - options::OPT_mno_long_calls)) { - if (A->getOption().matches(options::OPT_mlong_calls)) - UseLongCalls = true; - } - - Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls"); -} - static void getWebAssemblyTargetFeatures(const ArgList &Args, std::vector &Features) { handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); @@ -349,7 +334,7 @@ x86::getX86TargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::hexagon: - getHexagonTargetFeatures(Args, Features); + hexagon::getHexagonTargetFeatures(Args, Features); break; case llvm::Triple::wasm32: case llvm::Triple::wasm64: @@ -2616,6 +2601,33 @@ Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation); } +static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, + ArgStringList &CmdArgs) { + // -fsigned-char is default. + if (const Arg *A = Args.getLastArg(options::OPT_fsigned_char, + options::OPT_fno_signed_char, + options::OPT_funsigned_char, + options::OPT_fno_unsigned_char)) { + if (A->getOption().matches(options::OPT_funsigned_char) || + A->getOption().matches(options::OPT_fno_signed_char)) { + CmdArgs.push_back("-fno-signed-char"); + } + } else if (!isSignedCharDefault(T)) { + CmdArgs.push_back("-fno-signed-char"); + } + + if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar, + options::OPT_fno_short_wchar)) { + if (A->getOption().matches(options::OPT_fshort_wchar)) { + CmdArgs.push_back("-fwchar-type=short"); + CmdArgs.push_back("-fno-signed-wchar"); + } else { + CmdArgs.push_back("-fwchar-type=int"); + CmdArgs.push_back("-fsigned-wchar"); + } + } +} + static void RenderObjCOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, const ArgList &Args, ObjCRuntime &Runtime, bool InferCovariantReturns, @@ -3006,6 +3018,9 @@ Inputs.size() == 1) && "Unable to handle multiple inputs."); + const llvm::Triple *AuxTriple = + IsCuda ? getToolChain().getAuxTriple() : nullptr; + bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment(); bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment(); bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment(); @@ -3015,7 +3030,6 @@ // mode (i.e., getToolchain().getTriple() is NVPTX, not Windows), we need to // pass Windows-specific flags to cc1. if (IsCuda) { - const llvm::Triple *AuxTriple = getToolChain().getAuxTriple(); IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment(); IsWindowsGNU |= AuxTriple && AuxTriple->isWindowsGNUEnvironment(); IsWindowsCygnus |= AuxTriple && AuxTriple->isWindowsCygwinEnvironment(); @@ -3351,6 +3365,9 @@ options::OPT_fno_optimize_sibling_calls)) CmdArgs.push_back("-mdisable-tail-calls"); + Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses, + options::OPT_fno_fine_grained_bitfield_accesses); + // Handle segmented stacks. if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("-split-stacks"); @@ -4018,17 +4035,7 @@ getToolChain().getArch() == llvm::Triple::hexagon)) CmdArgs.push_back("-fshort-enums"); - // -fsigned-char is default. - if (Arg *A = Args.getLastArg( - options::OPT_fsigned_char, options::OPT_fno_signed_char, - options::OPT_funsigned_char, options::OPT_fno_unsigned_char)) { - if (A->getOption().matches(options::OPT_funsigned_char) || - A->getOption().matches(options::OPT_fno_signed_char)) { - CmdArgs.push_back("-fno-signed-char"); - } - } else if (!isSignedCharDefault(RawTriple)) { - CmdArgs.push_back("-fno-signed-char"); - } + RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs); // -fuse-cxa-atexit is default. if (!Args.hasFlag( @@ -4071,7 +4078,8 @@ if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) { LanguageStandard = llvm::StringSwitch(StdArg->getValue()) .Case("c++14", "-std=c++14") - .Case("c++latest", "-std=c++1z") + .Case("c++17", "-std=c++17") + .Case("c++latest", "-std=c++2a") .Default(""); if (LanguageStandard.empty()) D.Diag(clang::diag::warn_drv_unused_argument) @@ -4197,12 +4205,6 @@ options::OPT_mno_constant_cfstrings)) CmdArgs.push_back("-fno-constant-cfstrings"); - // -fshort-wchar default varies depending on platform; only - // pass if specified. - if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar, - options::OPT_fno_short_wchar)) - A->render(Args, CmdArgs); - // -fno-pascal-strings is default, only pass non-default. if (Args.hasFlag(options::OPT_fpascal_strings, options::OPT_fno_pascal_strings, false)) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/CommonArgs.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/CommonArgs.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/CommonArgs.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/CommonArgs.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -454,6 +454,14 @@ CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName)); } + + // Need this flag to turn on new pass manager via Gold plugin. + if (Args.hasFlag(options::OPT_fexperimental_new_pass_manager, + options::OPT_fno_experimental_new_pass_manager, + /* Default */ false)) { + CmdArgs.push_back("-plugin-opt=new-pass-manager"); + } + } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, @@ -552,8 +560,20 @@ SmallVectorImpl &RequiredSymbols) { const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Collect shared runtimes. - if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) { - SharedRuntimes.push_back("asan"); + if (SanArgs.needsSharedRt()) { + if (SanArgs.needsAsanRt()) { + SharedRuntimes.push_back("asan"); + if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) + HelperStaticRuntimes.push_back("asan-preinit"); + } + + if (SanArgs.needsUbsanRt()) { + if (SanArgs.requiresMinimalRuntime()) { + SharedRuntimes.push_back("ubsan_minimal"); + } else { + SharedRuntimes.push_back("ubsan_standalone"); + } + } } // The stats_client library is also statically linked into DSOs. @@ -561,18 +581,14 @@ StaticRuntimes.push_back("stats_client"); // Collect static runtimes. - if (Args.hasArg(options::OPT_shared) || TC.getTriple().isAndroid()) { - // Don't link static runtimes into DSOs or if compiling for Android. + if (Args.hasArg(options::OPT_shared) || SanArgs.needsSharedRt()) { + // Don't link static runtimes into DSOs or if -shared-libasan. return; } if (SanArgs.needsAsanRt()) { - if (SanArgs.needsSharedAsanRt()) { - HelperStaticRuntimes.push_back("asan-preinit"); - } else { - StaticRuntimes.push_back("asan"); - if (SanArgs.linkCXXRuntimes()) - StaticRuntimes.push_back("asan_cxx"); - } + StaticRuntimes.push_back("asan"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("asan_cxx"); } if (SanArgs.needsDfsanRt()) StaticRuntimes.push_back("dfsan"); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Cuda.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Cuda.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Cuda.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Cuda.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -87,8 +87,7 @@ LibDevicePath = InstallPath + "/nvvm/libdevice"; auto &FS = D.getVFS(); - if (!(FS.exists(IncludePath) && FS.exists(BinPath) && - FS.exists(LibDevicePath))) + if (!(FS.exists(IncludePath) && FS.exists(BinPath))) continue; // On Linux, we have both lib and lib64 directories, and we need to choose @@ -167,17 +166,9 @@ } } - // This code prevents IsValid from being set when - // no libdevice has been found. - bool allEmpty = true; - std::string LibDeviceFile; - for (auto key : LibDeviceMap.keys()) { - LibDeviceFile = LibDeviceMap.lookup(key); - if (!LibDeviceFile.empty()) - allEmpty = false; - } - - if (allEmpty) + // Check that we have found at least one libdevice that we can link in if + // -nocudalib hasn't been specified. + if (LibDeviceMap.empty() && !Args.hasArg(options::OPT_nocudalib)) continue; IsValid = true; @@ -551,9 +542,9 @@ // flags are not duplicated. // Also append the compute capability. if (DeviceOffloadKind == Action::OFK_OpenMP) { - for (Arg *A : Args){ + for (Arg *A : Args) { bool IsDuplicate = false; - for (Arg *DALArg : *DAL){ + for (Arg *DALArg : *DAL) { if (A == DALArg) { IsDuplicate = true; break; @@ -564,14 +555,9 @@ } StringRef Arch = DAL->getLastArgValue(options::OPT_march_EQ); - if (Arch.empty()) { - // Default compute capability for CUDA toolchain is the - // lowest compute capability supported by the installed - // CUDA version. - DAL->AddJoinedArg(nullptr, - Opts.getOption(options::OPT_march_EQ), - CudaInstallation.getLowestExistingArch()); - } + if (Arch.empty()) + DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), + CLANG_OPENMP_NVPTX_DEFAULT_ARCH); return DAL; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Cuda.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Cuda.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Cuda.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Cuda.h 2017-10-17 14:41:55.000000000 +0000 @@ -76,17 +76,6 @@ std::string getLibDeviceFile(StringRef Gpu) const { return LibDeviceMap.lookup(Gpu); } - /// \brief Get lowest available compute capability - /// for which a libdevice library exists. - std::string getLowestExistingArch() const { - std::string LibDeviceFile; - for (auto key : LibDeviceMap.keys()) { - LibDeviceFile = LibDeviceMap.lookup(key); - if (!LibDeviceFile.empty()) - return key; - } - return "sm_20"; - } }; namespace tools { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Darwin.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Darwin.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Darwin.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Darwin.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -986,6 +986,25 @@ llvm_unreachable("Unsupported platform"); } +/// Check if the link command contains a symbol export directive. +static bool hasExportSymbolDirective(const ArgList &Args) { + for (Arg *A : Args) { + if (!A->getOption().matches(options::OPT_Wl_COMMA) && + !A->getOption().matches(options::OPT_Xlinker)) + continue; + if (A->containsValue("-exported_symbols_list") || + A->containsValue("-exported_symbol")) + return true; + } + return false; +} + +/// Add an export directive for \p Symbol to the link command. +static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) { + CmdArgs.push_back("-exported_symbol"); + CmdArgs.push_back(Symbol); +} + void Darwin::addProfileRTLibs(const ArgList &Args, ArgStringList &CmdArgs) const { if (!needsProfileRT(Args)) return; @@ -994,6 +1013,16 @@ Args, CmdArgs, (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(), RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink)); + + // If we have a symbol export directive and we're linking in the profile + // runtime, automatically export symbols necessary to implement some of the + // runtime's functionality. + if (hasExportSymbolDirective(Args)) { + addExportedSymbol(CmdArgs, "_VPMergeHook"); + addExportedSymbol(CmdArgs, "___llvm_profile_filename"); + addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); + addExportedSymbol(CmdArgs, "_lprofCurFilename"); + } } void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, @@ -1049,7 +1078,8 @@ if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" - : "ubsan"); + : "ubsan", + Sanitize.needsSharedRt()); if (Sanitize.needsTsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Fuchsia.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Fuchsia.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Fuchsia.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Fuchsia.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -81,7 +81,7 @@ if (!Args.hasArg(options::OPT_shared)) { std::string Dyld = D.DyldPrefix; if (ToolChain.getSanitizerArgs().needsAsanRt() && - ToolChain.getSanitizerArgs().needsSharedAsanRt()) + ToolChain.getSanitizerArgs().needsSharedRt()) Dyld += "asan/"; Dyld += "ld.so.1"; CmdArgs.push_back("-dynamic-linker"); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Hexagon.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Hexagon.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Hexagon.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Hexagon.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -27,6 +27,22 @@ using namespace clang; using namespace llvm::opt; +// Hexagon target features. +void hexagon::getHexagonTargetFeatures(const ArgList &Args, + std::vector &Features) { + handleTargetFeaturesGroup(Args, Features, + options::OPT_m_hexagon_Features_Group); + + bool UseLongCalls = false; + if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, + options::OPT_mno_long_calls)) { + if (A->getOption().matches(options::OPT_mlong_calls)) + UseLongCalls = true; + } + + Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls"); +} + // Hexagon tools start. void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Hexagon.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Hexagon.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/Hexagon.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/Hexagon.h 2017-10-17 14:41:55.000000000 +0000 @@ -50,6 +50,10 @@ const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; + +void getHexagonTargetFeatures(const llvm::opt::ArgList &Args, + std::vector &Features); + } // end namespace hexagon. } // end namespace tools diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/MSVC.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/MSVC.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Driver/ToolChains/MSVC.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Driver/ToolChains/MSVC.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -375,7 +375,7 @@ if (TC.getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); - if (TC.getSanitizerArgs().needsSharedAsanRt() || + if (TC.getSanitizerArgs().needsSharedRt() || Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); @@ -1266,9 +1266,8 @@ if (MSVT.empty() && Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, IsWindowsMSVC)) { - // -fms-compatibility-version=18.00 is default. - // FIXME: Consider bumping this to 19 (MSVC2015) soon. - MSVT = VersionTuple(18); + // -fms-compatibility-version=19.11 is default, aka 2017 + MSVT = VersionTuple(19, 11); } return MSVT; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/BreakableToken.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/BreakableToken.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/BreakableToken.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/BreakableToken.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -599,6 +599,12 @@ } } +bool BreakableBlockComment::introducesBreakBefore(unsigned LineIndex) const { + // A break is introduced when we want delimiters on newline. + return LineIndex == 0 && DelimitersOnNewline && + Lines[0].substr(1).find_first_not_of(Blanks) != StringRef::npos; +} + void BreakableBlockComment::replaceWhitespaceBefore( unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit, Split SplitBefore, WhitespaceManager &Whitespaces) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/BreakableToken.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/BreakableToken.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/BreakableToken.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/BreakableToken.h 2017-10-17 14:41:55.000000000 +0000 @@ -58,6 +58,8 @@ /// operations that might be executed before the main line breaking occurs: /// - getSplitBefore, for finding a split such that the content preceding it /// needs to be specially reflown, +/// - introducesBreakBefore, for checking if reformatting the beginning +/// of the content introduces a line break before it, /// - getLineLengthAfterSplitBefore, for calculating the line length in columns /// of the remainder of the content after the beginning of the content has /// been reformatted, and @@ -135,6 +137,12 @@ return Split(StringRef::npos, 0); } + /// \brief Returns if a break before the content at \p LineIndex will be + /// inserted after the whitespace preceding the content has been reformatted. + virtual bool introducesBreakBefore(unsigned LineIndex) const { + return false; + } + /// \brief Returns the number of columns required to format the piece of line /// at \p LineIndex after the content preceding the whitespace range specified /// \p SplitBefore has been reformatted, but before any breaks are made to @@ -339,6 +347,7 @@ Split getSplitBefore(unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit, llvm::Regex &CommentPragmasRegex) const override; + bool introducesBreakBefore(unsigned LineIndex) const override; unsigned getLineLengthAfterSplitBefore(unsigned LineIndex, unsigned TailOffset, unsigned PreviousEndColumn, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/ContinuationIndenter.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/ContinuationIndenter.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/ContinuationIndenter.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/ContinuationIndenter.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -106,6 +106,7 @@ /*AvoidBinPacking=*/false, /*NoLineBreak=*/false)); State.LineContainsContinuedForLoopSection = false; + State.NoContinuation = false; State.StartOfStringLiteral = 0; State.StartOfLineLevel = 0; State.LowestLevelOnLine = 0; @@ -322,6 +323,12 @@ Previous.TokenText == "\'\\n\'")))) return true; + if (Previous.is(TT_BlockComment) && Previous.IsMultiline) + return true; + + if (State.NoContinuation) + return true; + return false; } @@ -331,6 +338,8 @@ const FormatToken &Current = *State.NextToken; assert(!State.Stack.empty()); + State.NoContinuation = false; + if ((Current.is(TT_ImplicitStringLiteral) && (Current.Previous->Tok.getIdentifierInfo() == nullptr || Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() == @@ -1286,7 +1295,7 @@ return 0; } } else if (Current.is(TT_BlockComment)) { - if (!Current.isTrailingComment() || !Style.ReflowComments || + if (!Style.ReflowComments || // If a comment token switches formatting, like // /* clang-format on */, we don't want to break it further, // but we may still want to adjust its indentation. @@ -1332,6 +1341,7 @@ ReflowInProgress = SplitBefore.first != StringRef::npos; TailOffset = ReflowInProgress ? (SplitBefore.first + SplitBefore.second) : 0; + BreakInserted = BreakInserted || Token->introducesBreakBefore(LineIndex); if (!DryRun) Token->replaceWhitespaceBefore(LineIndex, RemainingTokenColumns, RemainingSpace, SplitBefore, Whitespaces); @@ -1408,6 +1418,9 @@ State.Stack[i].BreakBeforeParameter = true; } + if (Current.is(TT_BlockComment)) + State.NoContinuation = true; + Penalty += Current.isStringLiteral() ? Style.PenaltyBreakString : Style.PenaltyBreakComment; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/ContinuationIndenter.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/ContinuationIndenter.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Format/ContinuationIndenter.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Format/ContinuationIndenter.h 2017-10-17 14:41:55.000000000 +0000 @@ -318,6 +318,9 @@ /// \brief \c true if this line contains a continued for-loop section. bool LineContainsContinuedForLoopSection; + /// \brief \c true if \p NextToken should not continue this line. + bool NoContinuation; + /// \brief The \c NestingLevel at the start of this line. unsigned StartOfLineLevel; @@ -364,6 +367,8 @@ if (LineContainsContinuedForLoopSection != Other.LineContainsContinuedForLoopSection) return LineContainsContinuedForLoopSection; + if (NoContinuation != Other.NoContinuation) + return NoContinuation; if (StartOfLineLevel != Other.StartOfLineLevel) return StartOfLineLevel < Other.StartOfLineLevel; if (LowestLevelOnLine != Other.LowestLevelOnLine) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/ASTUnit.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/ASTUnit.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/ASTUnit.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/ASTUnit.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1698,7 +1698,6 @@ PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; - PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0; PPOpts.SingleFileParseMode = SingleFileParse; // Override the resources path. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/CompilerInstance.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/CompilerInstance.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/CompilerInstance.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/CompilerInstance.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -386,6 +386,7 @@ Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(), getSourceManager(), getPCMCache(), *HeaderInfo, *this, PTHMgr, /*OwnsHeaderSearch=*/true, TUKind); + getTarget().adjust(getLangOpts()); PP->Initialize(getTarget(), getAuxTarget()); // Note that this is different then passing PTHMgr to Preprocessor's ctor. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/CompilerInvocation.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/CompilerInvocation.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/CompilerInvocation.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/CompilerInvocation.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -546,6 +546,9 @@ OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa); + Opts.FineGrainedBitfieldAccesses = + Args.hasFlag(OPT_ffine_grained_bitfield_accesses, + OPT_fno_fine_grained_bitfield_accesses, false); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); @@ -2138,6 +2141,12 @@ && Opts.OpenCLVersion >= 200); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts); + + // Enable [[]] attributes in C++11 by default. + Opts.DoubleSquareBracketAttributes = + Args.hasFlag(OPT_fdouble_square_bracket_attributes, + OPT_fno_double_square_bracket_attributes, Opts.CPlusPlus11); + Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts); Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS; Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse); @@ -2154,7 +2163,16 @@ Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules); Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); - Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false); + if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) { + Opts.WCharSize = llvm::StringSwitch(A->getValue()) + .Case("char", 1) + .Case("short", 2) + .Case("int", 4) + .Default(0); + if (Opts.WCharSize == 0) + Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue(); + } + Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; @@ -2748,6 +2766,13 @@ if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) { Res.getDiagnosticOpts().Warnings.push_back("spir-compat"); } + + // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. + if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && + !Res.getLangOpts()->Sanitize.empty()) { + Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false; + Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored); + } return Success; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/MultiplexConsumer.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/MultiplexConsumer.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/MultiplexConsumer.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/MultiplexConsumer.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -116,7 +116,8 @@ void ResolvedExceptionSpec(const FunctionDecl *FD) override; void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) override; + const FunctionDecl *Delete, + Expr *ThisArg) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; void StaticDataMemberInstantiated(const VarDecl *D) override; void DefaultArgumentInstantiated(const ParmVarDecl *D) override; @@ -183,9 +184,9 @@ Listeners[i]->DeducedReturnType(FD, ReturnType); } void MultiplexASTMutationListener::ResolvedOperatorDelete( - const CXXDestructorDecl *DD, const FunctionDecl *Delete) { + const CXXDestructorDecl *DD, const FunctionDecl *Delete, Expr *ThisArg) { for (auto *L : Listeners) - L->ResolvedOperatorDelete(DD, Delete); + L->ResolvedOperatorDelete(DD, Delete, ThisArg); } void MultiplexASTMutationListener::CompletedImplicitDefinition( const FunctionDecl *D) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/PrecompiledPreamble.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/PrecompiledPreamble.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/PrecompiledPreamble.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/PrecompiledPreamble.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -234,6 +234,8 @@ FrontendOpts.OutputFile = PreamblePCHFile->getFilePath(); PreprocessorOpts.PrecompiledPreambleBytes.first = 0; PreprocessorOpts.PrecompiledPreambleBytes.second = false; + // Inform preprocessor to record conditional stack when building the preamble. + PreprocessorOpts.GeneratePreamble = true; // Create the compiler instance to use for building the precompiled preamble. std::unique_ptr Clang( diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/PrintPreprocessedOutput.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/PrintPreprocessedOutput.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Frontend/PrintPreprocessedOutput.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Frontend/PrintPreprocessedOutput.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -720,6 +720,12 @@ // -traditional-cpp the lexer keeps /all/ whitespace, including comments. SourceLocation StartLoc = Tok.getLocation(); Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); + } else if (Tok.is(tok::eod)) { + // Don't print end of directive tokens, since they are typically newlines + // that mess up our line tracking. These come from unknown pre-processor + // directives or hash-prefixed comments in standalone assembly files. + PP.Lex(Tok); + continue; } else if (Tok.is(tok::annot_module_include)) { // PrintPPOutputPPCallbacks::InclusionDirective handles producing // appropriate output here. Ignore this token entirely. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/clflushoptintrin.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/clflushoptintrin.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/clflushoptintrin.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/clflushoptintrin.h 2017-10-17 14:41:55.000000000 +0000 @@ -32,7 +32,7 @@ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("clflushopt"))) static __inline__ void __DEFAULT_FN_ATTRS -_mm_clflushopt(char * __m) { +_mm_clflushopt(void const * __m) { __builtin_ia32_clflushopt(__m); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/clwbintrin.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/clwbintrin.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/clwbintrin.h 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/clwbintrin.h 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,52 @@ +/*===---- clwbintrin.h - CLWB intrinsic ------------------------------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __IMMINTRIN_H +#error "Never use directly; include instead." +#endif + +#ifndef __CLWBINTRIN_H +#define __CLWBINTRIN_H + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("clwb"))) + +/// \brief Writes back to memory the cache line (if modified) that contains the +/// linear address specified in \a __p from any level of the cache hierarchy in +/// the cache coherence domain +/// +/// \headerfile +/// +/// This intrinsic corresponds to the CLWB instruction. +/// +/// \param __p +/// A pointer to the memory location used to identify the cache line to be +/// written back. +static __inline__ void __DEFAULT_FN_ATTRS +_mm_clwb(void const *__p) { + __builtin_ia32_clwb(__p); +} + +#undef __DEFAULT_FN_ATTRS + +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/CMakeLists.txt llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/CMakeLists.txt --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/CMakeLists.txt 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/CMakeLists.txt 2017-10-17 14:41:55.000000000 +0000 @@ -33,6 +33,7 @@ clzerointrin.h cpuid.h clflushoptintrin.h + clwbintrin.h emmintrin.h f16cintrin.h float.h diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/immintrin.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/immintrin.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Headers/immintrin.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Headers/immintrin.h 2017-10-17 14:41:55.000000000 +0000 @@ -58,6 +58,10 @@ #include #endif +#if !defined(_MSC_VER) || __has_feature(modules) || defined(__CLWB__) +#include +#endif + #if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX__) #include #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Index/IndexDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Index/IndexDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Index/IndexDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Index/IndexDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -666,7 +666,6 @@ } bool VisitTemplateDecl(const TemplateDecl *D) { - // FIXME: Template parameters. // Index the default values for the template parameters. const NamedDecl *Parent = D->getTemplatedDecl(); @@ -683,7 +682,7 @@ } else if (const auto *TTPD = dyn_cast(TP)) { if (TTPD->hasDefaultArgument()) handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, - /*DC=*/nullptr); + TP->getLexicalDeclContext()); } } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Index/USRGeneration.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Index/USRGeneration.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Index/USRGeneration.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Index/USRGeneration.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -754,8 +754,12 @@ if (const FunctionProtoType *FT = T->getAs()) { Out << 'F'; VisitType(FT->getReturnType()); - for (const auto &I : FT->param_types()) + Out << '('; + for (const auto &I : FT->param_types()) { + Out << '#'; VisitType(I); + } + Out << ')'; if (FT->isVariadic()) Out << '.'; return; @@ -816,6 +820,25 @@ T = VT->getElementType(); continue; } + if (const auto *const AT = dyn_cast(T)) { + Out << '{'; + switch (AT->getSizeModifier()) { + case ArrayType::Static: + Out << 's'; + break; + case ArrayType::Star: + Out << '*'; + break; + case ArrayType::Normal: + Out << 'n'; + break; + } + if (const auto *const CAT = dyn_cast(T)) + Out << CAT->getSize(); + + T = AT->getElementType(); + continue; + } // Unhandled type. Out << ' '; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/Lexer.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/Lexer.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/Lexer.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/Lexer.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -2144,7 +2144,8 @@ // If we read multiple characters, and one of those characters was a \r or // \n, then we had an escaped newline within the comment. Emit diagnostic // unless the next line is also a // comment. - if (CurPtr != OldPtr+1 && C != '/' && CurPtr[0] != '/') { + if (CurPtr != OldPtr + 1 && C != '/' && + (CurPtr == BufferEnd + 1 || CurPtr[0] != '/')) { for (; OldPtr != CurPtr; ++OldPtr) if (OldPtr[0] == '\n' || OldPtr[0] == '\r') { // Okay, we found a // comment that ends in a newline, if the next @@ -3542,7 +3543,8 @@ } else if (LangOpts.Digraphs && Char == '%') { // '<%' -> '{' CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::l_brace; - } else if (Char == '#' && lexEditorPlaceholder(Result, CurPtr)) { + } else if (Char == '#' && /*Not a trigraph*/ SizeTmp == 1 && + lexEditorPlaceholder(Result, CurPtr)) { return true; } else { Kind = tok::less; @@ -3610,7 +3612,9 @@ if (LangOpts.Digraphs && Char == '>') { Kind = tok::r_square; // ':>' -> ']' CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); - } else if (LangOpts.CPlusPlus && Char == ':') { + } else if ((LangOpts.CPlusPlus || + LangOpts.DoubleSquareBracketAttributes) && + Char == ':') { Kind = tok::coloncolon; CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); } else { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/MacroArgs.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/MacroArgs.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/MacroArgs.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/MacroArgs.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -135,6 +135,16 @@ return Result; } +// This function assumes that the variadic arguments are the tokens +// corresponding to the last parameter (ellipsis) - and since tokens are +// separated by the 'eof' token, if that is the only token corresponding to that +// last parameter, we know no variadic arguments were supplied. +bool MacroArgs::invokedWithVariadicArgument(const MacroInfo *const MI) const { + if (!MI->isVariadic()) + return false; + const int VariadicArgIndex = getNumMacroArguments() - 1; + return getUnexpArgument(VariadicArgIndex)->isNot(tok::eof); +} /// ArgNeedsPreexpansion - If we can prove that the argument won't be affected /// by pre-expansion, return false. Otherwise, conservatively return true. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/PPDirectives.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/PPDirectives.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/PPDirectives.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/PPDirectives.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -2368,12 +2368,50 @@ // Otherwise, read the body of a function-like macro. While we are at it, // check C99 6.10.3.2p1: ensure that # operators are followed by macro // parameters in function-like macro expansions. + + VAOptDefinitionContext VAOCtx(*this); + while (Tok.isNot(tok::eod)) { LastTok = Tok; if (!Tok.isOneOf(tok::hash, tok::hashat, tok::hashhash)) { MI->AddTokenToBody(Tok); + if (VAOCtx.isVAOptToken(Tok)) { + // If we're already within a VAOPT, emit an error. + if (VAOCtx.isInVAOpt()) { + Diag(Tok, diag::err_pp_vaopt_nested_use); + return nullptr; + } + // Ensure VAOPT is followed by a '(' . + LexUnexpandedToken(Tok); + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use); + return nullptr; + } + MI->AddTokenToBody(Tok); + VAOCtx.sawVAOptFollowedByOpeningParens(Tok.getLocation()); + LexUnexpandedToken(Tok); + if (Tok.is(tok::hashhash)) { + Diag(Tok, diag::err_vaopt_paste_at_start); + return nullptr; + } + continue; + } else if (VAOCtx.isInVAOpt()) { + if (Tok.is(tok::r_paren)) { + if (VAOCtx.sawClosingParen()) { + const unsigned NumTokens = MI->getNumTokens(); + assert(NumTokens >= 3 && "Must have seen at least __VA_OPT__( " + "and a subsequent tok::r_paren"); + if (MI->getReplacementToken(NumTokens - 2).is(tok::hashhash)) { + Diag(Tok, diag::err_vaopt_paste_at_end); + return nullptr; + } + } + } else if (Tok.is(tok::l_paren)) { + VAOCtx.sawOpeningParen(Tok.getLocation()); + } + } // Get the next token of the macro. LexUnexpandedToken(Tok); continue; @@ -2414,12 +2452,14 @@ continue; } + // Our Token is a stringization operator. // Get the next token of the macro. LexUnexpandedToken(Tok); - // Check for a valid macro arg identifier. - if (Tok.getIdentifierInfo() == nullptr || - MI->getParameterNum(Tok.getIdentifierInfo()) == -1) { + // Check for a valid macro arg identifier or __VA_OPT__. + if (!VAOCtx.isVAOptToken(Tok) && + (Tok.getIdentifierInfo() == nullptr || + MI->getParameterNum(Tok.getIdentifierInfo()) == -1)) { // If this is assembler-with-cpp mode, we accept random gibberish after // the '#' because '#' is often a comment character. However, change @@ -2438,11 +2478,24 @@ // Things look ok, add the '#' and param name tokens to the macro. MI->AddTokenToBody(LastTok); - MI->AddTokenToBody(Tok); - LastTok = Tok; - // Get the next token of the macro. - LexUnexpandedToken(Tok); + // If the token following '#' is VAOPT, let the next iteration handle it + // and check it for correctness, otherwise add the token and prime the + // loop with the next one. + if (!VAOCtx.isVAOptToken(Tok)) { + MI->AddTokenToBody(Tok); + LastTok = Tok; + + // Get the next token of the macro. + LexUnexpandedToken(Tok); + } + } + if (VAOCtx.isInVAOpt()) { + assert(Tok.is(tok::eod) && "Must be at End Of preprocessing Directive"); + Diag(Tok, diag::err_pp_expected_after) + << LastTok.getKind() << tok::r_paren; + Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren; + return nullptr; } } MI->setDefinitionEndLoc(LastTok.getLocation()); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/Preprocessor.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/Preprocessor.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/Preprocessor.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/Preprocessor.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -121,12 +121,18 @@ // We haven't read anything from the external source. ReadMacrosFromExternalSource = false; - - // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. - // This gets unpoisoned where it is allowed. + + // "Poison" __VA_ARGS__, __VA_OPT__ which can only appear in the expansion of + // a macro. They get unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); - + if (getLangOpts().CPlusPlus2a) { + (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); + } else { + Ident__VA_OPT__ = nullptr; + } + // Initialize the pragma handlers. RegisterBuiltinPragmas(); @@ -667,13 +673,15 @@ // unpoisoned it if we're defining a C99 macro. if (II.isOutOfDate()) { bool CurrentIsPoisoned = false; - if (&II == Ident__VA_ARGS__) - CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned(); + const bool IsSpecialVariadicMacro = + &II == Ident__VA_ARGS__ || &II == Ident__VA_OPT__; + if (IsSpecialVariadicMacro) + CurrentIsPoisoned = II.isPoisoned(); updateOutOfDateIdentifier(II); Identifier.setKind(II.getTokenID()); - if (&II == Ident__VA_ARGS__) + if (IsSpecialVariadicMacro) II.setIsPoisoned(CurrentIsPoisoned); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/TokenLexer.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/TokenLexer.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Lex/TokenLexer.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Lex/TokenLexer.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -17,6 +17,7 @@ #include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/VariadicMacroSupport.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -168,6 +169,59 @@ return true; } +void TokenLexer::stringifyVAOPTContents( + SmallVectorImpl &ResultToks, const VAOptExpansionContext &VCtx, + const SourceLocation VAOPTClosingParenLoc) { + const int NumToksPriorToVAOpt = VCtx.getNumberOfTokensPriorToVAOpt(); + const unsigned int NumVAOptTokens = ResultToks.size() - NumToksPriorToVAOpt; + Token *const VAOPTTokens = + NumVAOptTokens ? &ResultToks[NumToksPriorToVAOpt] : nullptr; + + SmallVector ConcatenatedVAOPTResultToks; + // FIXME: Should we keep track within VCtx that we did or didnot + // encounter pasting - and only then perform this loop. + + // Perform token pasting (concatenation) prior to stringization. + for (unsigned int CurTokenIdx = 0; CurTokenIdx != NumVAOptTokens; + ++CurTokenIdx) { + if (VAOPTTokens[CurTokenIdx].is(tok::hashhash)) { + assert(CurTokenIdx != 0 && + "Can not have __VAOPT__ contents begin with a ##"); + Token &LHS = VAOPTTokens[CurTokenIdx - 1]; + pasteTokens(LHS, llvm::makeArrayRef(VAOPTTokens, NumVAOptTokens), + CurTokenIdx); + // Replace the token prior to the first ## in this iteration. + ConcatenatedVAOPTResultToks.back() = LHS; + if (CurTokenIdx == NumVAOptTokens) + break; + } + ConcatenatedVAOPTResultToks.push_back(VAOPTTokens[CurTokenIdx]); + } + + ConcatenatedVAOPTResultToks.push_back(VCtx.getEOFTok()); + // Get the SourceLocation that represents the start location within + // the macro definition that marks where this string is substituted + // into: i.e. the __VA_OPT__ and the ')' within the spelling of the + // macro definition, and use it to indicate that the stringified token + // was generated from that location. + const SourceLocation ExpansionLocStartWithinMacro = + getExpansionLocForMacroDefLoc(VCtx.getVAOptLoc()); + const SourceLocation ExpansionLocEndWithinMacro = + getExpansionLocForMacroDefLoc(VAOPTClosingParenLoc); + + Token StringifiedVAOPT = MacroArgs::StringifyArgument( + &ConcatenatedVAOPTResultToks[0], PP, VCtx.hasCharifyBefore() /*Charify*/, + ExpansionLocStartWithinMacro, ExpansionLocEndWithinMacro); + + if (VCtx.getLeadingSpaceForStringifiedToken()) + StringifiedVAOPT.setFlag(Token::LeadingSpace); + + StringifiedVAOPT.setFlag(Token::StringifiedInMacro); + // Resize (shrink) the token stream to just capture this stringified token. + ResultToks.resize(NumToksPriorToVAOpt + 1); + ResultToks.back() = StringifiedVAOPT; +} + /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. void TokenLexer::ExpandFunctionArguments() { @@ -178,10 +232,13 @@ // we install the newly expanded sequence as the new 'Tokens' list. bool MadeChange = false; + const bool CalledWithVariadicArguments = + ActualArgs->invokedWithVariadicArgument(Macro); + + VAOptExpansionContext VCtx(PP); + for (unsigned I = 0, E = NumTokens; I != E; ++I) { - // If we found the stringify operator, get the argument stringified. The - // preprocessor already verified that the following token is a macro name - // when the #define was parsed. + const Token &CurTok = Tokens[I]; // We don't want a space for the next token after a paste // operator. In valid code, the token will get smooshed onto the @@ -192,10 +249,98 @@ if (I != 0 && !Tokens[I-1].is(tok::hashhash) && CurTok.hasLeadingSpace()) NextTokGetsSpace = true; + if (VCtx.isVAOptToken(CurTok)) { + MadeChange = true; + assert(Tokens[I + 1].is(tok::l_paren) && + "__VA_OPT__ must be followed by '('"); + + ++I; // Skip the l_paren + VCtx.sawVAOptFollowedByOpeningParens(CurTok.getLocation(), + ResultToks.size()); + + continue; + } + + // We have entered into the __VA_OPT__ context, so handle tokens + // appropriately. + if (VCtx.isInVAOpt()) { + // If we are about to process a token that is either an argument to + // __VA_OPT__ or its closing rparen, then: + // 1) If the token is the closing rparen that exits us out of __VA_OPT__, + // perform any necessary stringification or placemarker processing, + // and/or skip to the next token. + // 2) else if macro was invoked without variadic arguments skip this + // token. + // 3) else (macro was invoked with variadic arguments) process the token + // normally. + + if (Tokens[I].is(tok::l_paren)) + VCtx.sawOpeningParen(Tokens[I].getLocation()); + // Continue skipping tokens within __VA_OPT__ if the macro was not + // called with variadic arguments, else let the rest of the loop handle + // this token. Note sawClosingParen() returns true only if the r_paren matches + // the closing r_paren of the __VA_OPT__. + if (!Tokens[I].is(tok::r_paren) || !VCtx.sawClosingParen()) { + if (!CalledWithVariadicArguments) { + // Skip this token. + continue; + } + // ... else the macro was called with variadic arguments, and we do not + // have a closing rparen - so process this token normally. + + } else { + // Current token is the closing r_paren which marks the end of the + // __VA_OPT__ invocation, so handle any place-marker pasting (if + // empty) by removing hashhash either before (if exists) or after. And + // also stringify the entire contents if VAOPT was preceded by a hash, + // but do so only after any token concatenation that needs to occur + // within the contents of VAOPT. + + if (VCtx.hasStringifyOrCharifyBefore()) { + // Replace all the tokens just added from within VAOPT into a single + // stringified token. This requires token-pasting to eagerly occur + // within these tokens. If either the contents of VAOPT were empty + // or the macro wasn't called with any variadic arguments, the result + // is a token that represents an empty string. + stringifyVAOPTContents(ResultToks, VCtx, + /*ClosingParenLoc*/ Tokens[I].getLocation()); + + } else if (/*No tokens within VAOPT*/ !( + ResultToks.size() - VCtx.getNumberOfTokensPriorToVAOpt())) { + // Treat VAOPT as a placemarker token. Eat either the '##' before the + // RHS/VAOPT (if one exists, suggesting that the LHS (if any) to that + // hashhash was not a placemarker) or the '##' + // after VAOPT, but not both. + + if (ResultToks.size() && ResultToks.back().is(tok::hashhash)) { + ResultToks.pop_back(); + } else if ((I + 1 != E) && Tokens[I + 1].is(tok::hashhash)) { + ++I; // Skip the following hashhash. + } + } + VCtx.reset(); + // We processed __VA_OPT__'s closing paren (and the exit out of + // __VA_OPT__), so skip to the next token. + continue; + } + } + + // If we found the stringify operator, get the argument stringified. The + // preprocessor already verified that the following token is a macro + // parameter or __VA_OPT__ when the #define was lexed. + if (CurTok.isOneOf(tok::hash, tok::hashat)) { int ArgNo = Macro->getParameterNum(Tokens[I+1].getIdentifierInfo()); - assert(ArgNo != -1 && "Token following # is not an argument?"); - + assert((ArgNo != -1 || VCtx.isVAOptToken(Tokens[I + 1])) && + "Token following # is not an argument or __VA_OPT__!"); + + if (ArgNo == -1) { + // Handle the __VA_OPT__ case. + VCtx.sawHashOrHashAtBefore(NextTokGetsSpace, + CurTok.is(tok::hashat)); + continue; + } + // Else handle the simple argument case. SourceLocation ExpansionLocStart = getExpansionLocForMacroDefLoc(CurTok.getLocation()); SourceLocation ExpansionLocEnd = @@ -232,7 +377,9 @@ !ResultToks.empty() && ResultToks.back().is(tok::hashhash); bool PasteBefore = I != 0 && Tokens[I-1].is(tok::hashhash); bool PasteAfter = I+1 != E && Tokens[I+1].is(tok::hashhash); - assert(!NonEmptyPasteBefore || PasteBefore); + + assert((!NonEmptyPasteBefore || PasteBefore || VCtx.isInVAOpt()) && + "unexpected ## in ResultToks"); // Otherwise, if this is not an argument token, just add the token to the // output buffer. @@ -384,7 +531,13 @@ assert(PasteBefore); if (NonEmptyPasteBefore) { assert(ResultToks.back().is(tok::hashhash)); - ResultToks.pop_back(); + // Do not remove the paste operator if it is the one before __VA_OPT__ + // (and we are still processing tokens within VA_OPT). We handle the case + // of removing the paste operator if __VA_OPT__ reduces to the notional + // placemarker above when we encounter the closing paren of VA_OPT. + if (!VCtx.isInVAOpt() || + ResultToks.size() > VCtx.getNumberOfTokensPriorToVAOpt()) + ResultToks.pop_back(); } // If this is the __VA_ARGS__ token, and if the argument wasn't provided, @@ -847,9 +1000,8 @@ /// \brief Creates SLocEntries and updates the locations of macro argument /// tokens to their new expanded locations. /// -/// \param ArgIdDefLoc the location of the macro argument id inside the macro +/// \param ArgIdSpellLoc the location of the macro argument id inside the macro /// definition. -/// \param Tokens the macro argument tokens to update. void TokenLexer::updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc, Token *begin_tokens, Token *end_tokens) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/ParseDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/ParseDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/ParseDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/ParseDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1562,7 +1562,7 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID) { for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) { - if (!Attr->isCXX11Attribute()) + if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute()) continue; if (Attr->getKind() == AttributeList::UnknownAttribute) Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored) @@ -2925,7 +2925,7 @@ case tok::l_square: case tok::kw_alignas: - if (!getLangOpts().CPlusPlus11 || !isCXX11AttributeSpecifier()) + if (!standardAttributesAllowed() || !isCXX11AttributeSpecifier()) goto DoneWithDeclSpec; ProhibitAttributes(attrs); @@ -3778,7 +3778,8 @@ /// semicolon. /// /// struct-declaration: -/// specifier-qualifier-list struct-declarator-list +/// [C2x] attributes-specifier-seq[opt] +/// specifier-qualifier-list struct-declarator-list /// [GNU] __extension__ struct-declaration /// [GNU] specifier-qualifier-list /// struct-declarator-list: @@ -3802,6 +3803,11 @@ return ParseStructDeclaration(DS, FieldsCallback); } + // Parse leading attributes. + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + DS.takeAttributesFrom(Attrs); + // Parse the common specifier-qualifiers-list piece. ParseSpecifierQualifierList(DS); @@ -4412,9 +4418,11 @@ ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); ProhibitAttributes(attrs); // GNU-style attributes are prohibited. - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { - if (!getLangOpts().CPlusPlus1z) - Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) + if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { + if (getLangOpts().CPlusPlus) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z + ? diag::warn_cxx14_compat_ns_enum_attribute + : diag::ext_ns_enum_attribute) << 1 /*enumerator*/; ParseCXX11Attributes(attrs); } @@ -5024,7 +5032,7 @@ DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed, bool IdentifierRequired, Optional> CodeCompletionHandler) { - if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) && + if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); ParseCXX11Attributes(attrs); @@ -5961,7 +5969,7 @@ SmallVector DynamicExceptionRanges; ExprResult NoexceptExpr; CachedTokens *ExceptionSpecTokens = nullptr; - ParsedAttributes FnAttrs(AttrFactory); + ParsedAttributesWithRange FnAttrs(AttrFactory); TypeResult TrailingReturnType; /* LocalEndLoc is the end location for the local FunctionTypeLoc. @@ -5982,6 +5990,11 @@ RParenLoc = Tracker.getCloseLocation(); LocalEndLoc = RParenLoc; EndLoc = RParenLoc; + + // If there are attributes following the identifier list, parse them and + // prohibit them. + MaybeParseCXX11Attributes(FnAttrs); + ProhibitAttributes(FnAttrs); } else { if (Tok.isNot(tok::r_paren)) ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, @@ -5989,7 +6002,8 @@ else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - HasProto = ParamInfo.size() || getLangOpts().CPlusPlus; + HasProto = ParamInfo.size() || getLangOpts().CPlusPlus + || getLangOpts().OpenCL; // If we have the closing ')', eat it. Tracker.consumeClose(); @@ -6087,6 +6101,8 @@ TrailingReturnType = ParseTrailingReturnType(Range); EndLoc = Range.getEnd(); } + } else if (standardAttributesAllowed()) { + MaybeParseCXX11Attributes(FnAttrs); } } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/ParseDeclCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/ParseDeclCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/ParseDeclCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/ParseDeclCXX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -77,9 +77,10 @@ ParsedAttributesWithRange attrs(AttrFactory); SourceLocation attrLoc; if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { - if (!getLangOpts().CPlusPlus1z) - Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) - << 0 /*namespace*/; + Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z + ? diag::warn_cxx14_compat_ns_enum_attribute + : diag::ext_ns_enum_attribute) + << 0 /*namespace*/; attrLoc = Tok.getLocation(); ParseCXX11Attributes(attrs); } @@ -3813,7 +3814,7 @@ } static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, - IdentifierInfo *ScopeName) { + IdentifierInfo *ScopeName) { switch (AttributeList::getKind(AttrName, ScopeName, AttributeList::AS_CXX11)) { case AttributeList::AT_CarriesDependency: @@ -3852,11 +3853,14 @@ SourceLocation ScopeLoc) { assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); SourceLocation LParenLoc = Tok.getLocation(); + const LangOptions &LO = getLangOpts(); + AttributeList::Syntax Syntax = + LO.CPlusPlus ? AttributeList::AS_CXX11 : AttributeList::AS_C2x; // If the attribute isn't known, we will not attempt to parse any // arguments. - if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName, - getTargetInfo(), getLangOpts())) { + if (!hasAttribute(LO.CPlusPlus ? AttrSyntax::CXX : AttrSyntax::C, ScopeName, + AttrName, getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); SkipUntil(tok::r_paren); @@ -3867,7 +3871,7 @@ // GNU-scoped attributes have some special cases to handle GNU-specific // behaviors. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, AttributeList::AS_CXX11, nullptr); + ScopeLoc, Syntax, nullptr); return true; } @@ -3876,11 +3880,11 @@ if (ScopeName && ScopeName->getName() == "clang") NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, AttributeList::AS_CXX11); + ScopeLoc, Syntax); else NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, AttributeList::AS_CXX11); + ScopeName, ScopeLoc, Syntax); const AttributeList *Attr = Attrs.getList(); if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { @@ -3906,7 +3910,7 @@ return true; } -/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. +/// ParseCXX11AttributeSpecifier - Parse a C++11 or C2x attribute-specifier. /// /// [C++11] attribute-specifier: /// '[' '[' attribute-list ']' ']' @@ -3938,8 +3942,8 @@ return; } - assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) - && "Not a C++11 attribute list"); + assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) && + "Not a double square bracket attribute list"); Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute); @@ -4015,10 +4019,12 @@ ScopeName, ScopeLoc); if (!AttrParsed) - attrs.addNew(AttrName, - SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, - AttrLoc), - ScopeName, ScopeLoc, nullptr, 0, AttributeList::AS_CXX11); + attrs.addNew( + AttrName, + SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), + ScopeName, ScopeLoc, nullptr, 0, + getLangOpts().CPlusPlus ? AttributeList::AS_CXX11 + : AttributeList::AS_C2x); if (TryConsumeToken(tok::ellipsis)) Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) @@ -4033,13 +4039,13 @@ SkipUntil(tok::r_square); } -/// ParseCXX11Attributes - Parse a C++11 attribute-specifier-seq. +/// ParseCXX11Attributes - Parse a C++11 or C2x attribute-specifier-seq. /// /// attribute-specifier-seq: /// attribute-specifier-seq[opt] attribute-specifier void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *endLoc) { - assert(getLangOpts().CPlusPlus11); + assert(standardAttributesAllowed()); SourceLocation StartLoc = Tok.getLocation(), Loc; if (!endLoc) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/ParseExprCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/ParseExprCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/ParseExprCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/ParseExprCXX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1354,7 +1354,6 @@ if (ExpectAndConsume(tok::greater)) return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less); - SourceLocation LParenLoc, RParenLoc; BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume(diag::err_expected_lparen_after, CastName)) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/Parser.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/Parser.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Parse/Parser.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Parse/Parser.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -2048,7 +2048,7 @@ SourceLocation StartLoc = Tok.getLocation(); Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export) - ? Sema::ModuleDeclKind::Module + ? Sema::ModuleDeclKind::Interface : Sema::ModuleDeclKind::Implementation; assert(Tok.is(tok::kw_module) && "not a module declaration"); @@ -2057,7 +2057,7 @@ if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) && Tok.getIdentifierInfo()->isStr("partition")) { // If 'partition' is present, this must be a module interface unit. - if (MDK != Sema::ModuleDeclKind::Module) + if (MDK != Sema::ModuleDeclKind::Interface) Diag(Tok.getLocation(), diag::err_module_implementation_partition) << FixItHint::CreateInsertion(ModuleLoc, "export "); MDK = Sema::ModuleDeclKind::Partition; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/AttributeList.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/AttributeList.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/AttributeList.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/AttributeList.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -114,7 +114,8 @@ // Normalize the attribute name, __foo__ becomes foo. This is only allowable // for GNU attributes. bool IsGNU = SyntaxUsed == AttributeList::AS_GNU || - (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu"); + ((SyntaxUsed == AttributeList::AS_CXX11 || + SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu"); if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && AttrName.endswith("__")) AttrName = AttrName.slice(2, AttrName.size() - 2); @@ -135,7 +136,7 @@ // Ensure that in the case of C++11 attributes, we look for '::foo' if it is // unscoped. - if (ScopeName || SyntaxUsed == AS_CXX11) + if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x) FullName += "::"; FullName += AttrName; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/MultiplexExternalSemaSource.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/MultiplexExternalSemaSource.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/MultiplexExternalSemaSource.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/MultiplexExternalSemaSource.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -19,8 +19,6 @@ ///\brief Constructs a new multiplexing external sema source and appends the /// given element to it. /// -///\param[in] source - An ExternalSemaSource. -/// MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1, ExternalSemaSource &s2){ Sources.push_back(&s1); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaChecking.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaChecking.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaChecking.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaChecking.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -340,7 +340,7 @@ // First argument is an ndrange_t type. Expr *NDRangeArg = TheCall->getArg(0); - if (NDRangeArg->getType().getAsString() != "ndrange_t") { + if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") { S.Diag(NDRangeArg->getLocStart(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "'ndrange_t'"; @@ -784,8 +784,11 @@ case Builtin::BIto_local: Qual.setAddressSpace(LangAS::opencl_local); break; + case Builtin::BIto_private: + Qual.setAddressSpace(LangAS::opencl_private); + break; default: - Qual.removeAddressSpace(); + llvm_unreachable("Invalid builtin function"); } Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( RT.getUnqualifiedType(), Qual))); @@ -3137,7 +3140,7 @@ // Treat this argument as _Nonnull as we want to show a warning if // NULL is passed into it. CheckNonNullArgument(*this, ValArg, DRE->getLocStart()); - unsigned AS = 0; + LangAS AS = LangAS::Default; // Keep address space of non-atomic pointer type. if (const PointerType *PtrTy = ValArg->getType()->getAs()) { @@ -8553,19 +8556,71 @@ void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); -bool IsZero(Sema &S, Expr *E) { +bool IsEnumConstOrFromMacro(Sema &S, Expr *E) { // Suppress cases where we are comparing against an enum constant. if (const DeclRefExpr *DR = dyn_cast(E->IgnoreParenImpCasts())) if (isa(DR->getDecl())) - return false; + return true; // Suppress cases where the '0' value is expanded from a macro. if (E->getLocStart().isMacroID()) - return false; + return true; - llvm::APSInt Value; - return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; + return false; +} + +bool isNonBooleanIntegerValue(Expr *E) { + return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType(); +} + +bool isNonBooleanUnsignedValue(Expr *E) { + // We are checking that the expression is not known to have boolean value, + // is an integer type; and is either unsigned after implicit casts, + // or was unsigned before implicit casts. + return isNonBooleanIntegerValue(E) && + (!E->getType()->isSignedIntegerType() || + !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType()); +} + +enum class LimitType { + Max, // e.g. 32767 for short + Min // e.g. -32768 for short +}; + +/// Checks whether Expr 'Constant' may be the +/// std::numeric_limits<>::max() or std::numeric_limits<>::min() +/// of the Expr 'Other'. If true, then returns the limit type (min or max). +/// The Value is the evaluation of Constant +llvm::Optional IsTypeLimit(Sema &S, Expr *Constant, Expr *Other, + const llvm::APSInt &Value) { + if (IsEnumConstOrFromMacro(S, Constant)) + return llvm::Optional(); + + if (isNonBooleanUnsignedValue(Other) && Value == 0) + return LimitType::Min; + + // TODO: Investigate using GetExprRange() to get tighter bounds + // on the bit ranges. + QualType OtherT = Other->IgnoreParenImpCasts()->getType(); + if (const auto *AT = OtherT->getAs()) + OtherT = AT->getValueType(); + + IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); + + if (llvm::APSInt::isSameValue( + llvm::APSInt::getMaxValue(OtherRange.Width, + OtherT->isUnsignedIntegerType()), + Value)) + return LimitType::Max; + + if (llvm::APSInt::isSameValue( + llvm::APSInt::getMinValue(OtherRange.Width, + OtherT->isUnsignedIntegerType()), + Value)) + return LimitType::Min; + + return llvm::Optional(); } bool HasEnumType(Expr *E) { @@ -8580,63 +8635,60 @@ return E->getType()->isEnumeralType(); } -bool isNonBooleanUnsignedValue(Expr *E) { - // We are checking that the expression is not known to have boolean value, - // is an integer type; and is either unsigned after implicit casts, - // or was unsigned before implicit casts. - return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType() && - (!E->getType()->isSignedIntegerType() || - !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType()); -} - -bool CheckTautologicalComparisonWithZero(Sema &S, BinaryOperator *E) { - // Disable warning in template instantiations. - if (S.inTemplateInstantiation()) +bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, Expr *Constant, + Expr *Other, const llvm::APSInt &Value, + bool RhsConstant) { + // Disable warning in template instantiations + // and only analyze <, >, <= and >= operations. + if (S.inTemplateInstantiation() || !E->isRelationalOp()) return false; - // bool values are handled by DiagnoseOutOfRangeComparison(). - BinaryOperatorKind Op = E->getOpcode(); - if (E->isValueDependent()) + + QualType OType = Other->IgnoreParenImpCasts()->getType(); + + llvm::Optional ValueType; // Which limit (min/max) is the constant? + + if (!(isNonBooleanIntegerValue(Other) && + (ValueType = IsTypeLimit(S, Constant, Other, Value)))) return false; - Expr *LHS = E->getLHS(); - Expr *RHS = E->getRHS(); + bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant; + bool ResultWhenConstEqualsOther = (Op == BO_LE || Op == BO_GE); + bool ResultWhenConstNeOther = + ConstIsLowerBound ^ (ValueType == LimitType::Max); + if (ResultWhenConstEqualsOther != ResultWhenConstNeOther) + return false; // The comparison is not tautological. + + const bool Result = ResultWhenConstEqualsOther; + + unsigned Diag = (isNonBooleanUnsignedValue(Other) && Value == 0) + ? (HasEnumType(Other) + ? diag::warn_unsigned_enum_always_true_comparison + : diag::warn_unsigned_always_true_comparison) + : diag::warn_tautological_constant_compare; - bool Match = true; + // Should be enough for uint128 (39 decimal digits) + SmallString<64> PrettySourceValue; + llvm::raw_svector_ostream OS(PrettySourceValue); + OS << Value; - if (Op == BO_LT && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) { - S.Diag(E->getOperatorLoc(), - HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison - : diag::warn_lunsigned_always_true_comparison) - << "< 0" << false << LHS->getSourceRange() << RHS->getSourceRange(); - } else if (Op == BO_GE && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) { - S.Diag(E->getOperatorLoc(), - HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison - : diag::warn_lunsigned_always_true_comparison) - << ">= 0" << true << LHS->getSourceRange() << RHS->getSourceRange(); - } else if (Op == BO_GT && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) { - S.Diag(E->getOperatorLoc(), - HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison - : diag::warn_runsigned_always_true_comparison) - << "0 >" << false << LHS->getSourceRange() << RHS->getSourceRange(); - } else if (Op == BO_LE && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) { - S.Diag(E->getOperatorLoc(), - HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison - : diag::warn_runsigned_always_true_comparison) - << "0 <=" << true << LHS->getSourceRange() << RHS->getSourceRange(); - } else - Match = false; + S.Diag(E->getOperatorLoc(), Diag) + << RhsConstant << OType << E->getOpcodeStr() << OS.str() << Result + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); - return Match; + return true; } -void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, +bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, Expr *Other, const llvm::APSInt &Value, bool RhsConstant) { // Disable warning in template instantiations. if (S.inTemplateInstantiation()) - return; + return false; + + Constant = Constant->IgnoreParenImpCasts(); + Other = Other->IgnoreParenImpCasts(); // TODO: Investigate using GetExprRange() to get tighter bounds // on the bit ranges. @@ -8648,10 +8700,6 @@ bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue(); - // 0 values are handled later by CheckTautologicalComparisonWithZero(). - if ((Value == 0) && (!OtherIsBooleanType)) - return; - BinaryOperatorKind op = E->getOpcode(); bool IsTrue = true; @@ -8667,7 +8715,7 @@ QualType CommonT = E->getLHS()->getType(); if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT)) - return; + return false; assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) && "comparison with non-integer type"); @@ -8682,38 +8730,38 @@ // Check that the constant is representable in type OtherT. if (ConstantSigned) { if (OtherWidth >= Value.getMinSignedBits()) - return; + return false; } else { // !ConstantSigned if (OtherWidth >= Value.getActiveBits() + 1) - return; + return false; } } else { // !OtherSigned // Check that the constant is representable in type OtherT. // Negative values are out of range. if (ConstantSigned) { if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits()) - return; + return false; } else { // !ConstantSigned if (OtherWidth >= Value.getActiveBits()) - return; + return false; } } } else { // !CommonSigned if (OtherRange.NonNegative) { if (OtherWidth >= Value.getActiveBits()) - return; + return false; } else { // OtherSigned assert(!ConstantSigned && "Two signed types converted to unsigned types."); // Check to see if the constant is representable in OtherT. if (OtherWidth > Value.getActiveBits()) - return; + return false; // Check to see if the constant is equivalent to a negative value // cast to CommonT. if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) && Value.isNegative() && Value.getMinSignedBits() <= OtherWidth) - return; + return false; // The constant value rests between values that OtherT can represent // after conversion. Relational comparison still works, but equality // comparisons will be tautological. @@ -8726,7 +8774,7 @@ if (op == BO_EQ || op == BO_NE) { IsTrue = op == BO_NE; } else if (EqualityOnly) { - return; + return false; } else if (RhsConstant) { if (op == BO_GT || op == BO_GE) IsTrue = !PositiveConstant; @@ -8814,7 +8862,7 @@ } else if (CmpRes == ATrue) { IsTrue = true; } else { - return; + return false; } } @@ -8837,6 +8885,8 @@ << OS.str() << LiteralOrBoolConstant << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); + + return true; } /// Analyze the operands of the given comparison. Implements the @@ -8862,44 +8912,48 @@ if (E->isValueDependent()) return AnalyzeImpConvsInComparison(S, E); - Expr *LHS = E->getLHS()->IgnoreParenImpCasts(); - Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); - - bool IsComparisonConstant = false; - - // Check whether an integer constant comparison results in a value - // of 'true' or 'false'. + Expr *LHS = E->getLHS(); + Expr *RHS = E->getRHS(); + if (T->isIntegralType(S.Context)) { llvm::APSInt RHSValue; - bool IsRHSIntegralLiteral = - RHS->isIntegerConstantExpr(RHSValue, S.Context); llvm::APSInt LHSValue; - bool IsLHSIntegralLiteral = - LHS->isIntegerConstantExpr(LHSValue, S.Context); - if (IsRHSIntegralLiteral && !IsLHSIntegralLiteral) - DiagnoseOutOfRangeComparison(S, E, RHS, LHS, RHSValue, true); - else if (!IsRHSIntegralLiteral && IsLHSIntegralLiteral) - DiagnoseOutOfRangeComparison(S, E, LHS, RHS, LHSValue, false); - else - IsComparisonConstant = - (IsRHSIntegralLiteral && IsLHSIntegralLiteral); - } else if (!T->hasUnsignedIntegerRepresentation()) - IsComparisonConstant = E->isIntegerConstantExpr(S.Context); - - // We don't care about value-dependent expressions or expressions - // whose result is a constant. - if (IsComparisonConstant) - return AnalyzeImpConvsInComparison(S, E); - // If this is a tautological comparison, suppress -Wsign-compare. - if (CheckTautologicalComparisonWithZero(S, E)) - return AnalyzeImpConvsInComparison(S, E); + bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context); + bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context); + + // We don't care about expressions whose result is a constant. + if (IsRHSIntegralLiteral && IsLHSIntegralLiteral) + return AnalyzeImpConvsInComparison(S, E); + + // We only care about expressions where just one side is literal + if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) { + // Is the constant on the RHS or LHS? + const bool RhsConstant = IsRHSIntegralLiteral; + Expr *Const = RhsConstant ? RHS : LHS; + Expr *Other = RhsConstant ? LHS : RHS; + const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue; + + // Check whether an integer constant comparison results in a value + // of 'true' or 'false'. + + if (CheckTautologicalComparison(S, E, Const, Other, Value, RhsConstant)) + return AnalyzeImpConvsInComparison(S, E); - // We don't do anything special if this isn't an unsigned integral - // comparison: we're only interested in integral comparisons, and - // signed comparisons only happen in cases we don't care to warn about. - if (!T->hasUnsignedIntegerRepresentation()) + if (DiagnoseOutOfRangeComparison(S, E, Const, Other, Value, RhsConstant)) + return AnalyzeImpConvsInComparison(S, E); + } + } + + if (!T->hasUnsignedIntegerRepresentation()) { + // We don't do anything special if this isn't an unsigned integral + // comparison: we're only interested in integral comparisons, and + // signed comparisons only happen in cases we don't care to warn about. return AnalyzeImpConvsInComparison(S, E); + } + + LHS = LHS->IgnoreParenImpCasts(); + RHS = RHS->IgnoreParenImpCasts(); // Check to see if one of the (unmodified) operands is of different // signedness. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/Sema.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/Sema.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/Sema.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/Sema.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -930,6 +930,17 @@ } if (TUKind == TU_Module) { + // If we are building a module interface unit, we need to have seen the + // module declaration by now. + if (getLangOpts().getCompilingModule() == + LangOptions::CMK_ModuleInterface && + ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) { + // FIXME: Make a better guess as to where to put the module declaration. + Diag(getSourceManager().getLocForStartOfFile( + getSourceManager().getMainFileID()), + diag::err_module_declaration_missing); + } + // If we are building a module, resolve all of the exported declarations // now. if (Module *CurrentModule = PP.getCurrentModule()) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDeclAttr.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDeclAttr.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDeclAttr.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDeclAttr.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -4385,7 +4385,7 @@ static bool isValidSwiftContextType(QualType type) { if (!type->hasPointerRepresentation()) return type->isDependentType(); - return type->getPointeeType().getAddressSpace() == 0; + return type->getPointeeType().getAddressSpace() == LangAS::Default; } /// Pointers and references in the default address space. @@ -4397,7 +4397,7 @@ } else { return type->isDependentType(); } - return type.getAddressSpace() == 0; + return type.getAddressSpace() == LangAS::Default; } /// Pointers and references to pointers in the default address space. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1448,6 +1448,46 @@ F.done(); } +/// We've determined that \p New is a redeclaration of \p Old. Check that they +/// have compatible owning modules. +bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) { + // FIXME: The Modules TS is not clear about how friend declarations are + // to be treated. It's not meaningful to have different owning modules for + // linkage in redeclarations of the same entity, so for now allow the + // redeclaration and change the owning modules to match. + if (New->getFriendObjectKind() && + Old->getOwningModuleForLinkage() != New->getOwningModuleForLinkage()) { + New->setLocalOwningModule(Old->getOwningModule()); + makeMergedDefinitionVisible(New); + return false; + } + + Module *NewM = New->getOwningModule(); + Module *OldM = Old->getOwningModule(); + if (NewM == OldM) + return false; + + // FIXME: Check proclaimed-ownership-declarations here too. + bool NewIsModuleInterface = NewM && NewM->Kind == Module::ModuleInterfaceUnit; + bool OldIsModuleInterface = OldM && OldM->Kind == Module::ModuleInterfaceUnit; + if (NewIsModuleInterface || OldIsModuleInterface) { + // C++ Modules TS [basic.def.odr] 6.2/6.7 [sic]: + // if a declaration of D [...] appears in the purview of a module, all + // other such declarations shall appear in the purview of the same module + Diag(New->getLocation(), diag::err_mismatched_owning_module) + << New + << NewIsModuleInterface + << (NewIsModuleInterface ? NewM->getFullModuleName() : "") + << OldIsModuleInterface + << (OldIsModuleInterface ? OldM->getFullModuleName() : ""); + Diag(Old->getLocation(), diag::note_previous_declaration); + New->setInvalidDecl(); + return true; + } + + return false; +} + static bool isUsingDecl(NamedDecl *D) { return isa(D) || isa(D) || @@ -1683,7 +1723,8 @@ dyn_cast(Init); if (Construct && !Construct->isElidable()) { CXXConstructorDecl *CD = Construct->getConstructor(); - if (!CD->isTrivial() && !RD->hasAttr()) + if (!CD->isTrivial() && !RD->hasAttr() && + !VD->evaluateValue()) return false; } } @@ -2627,7 +2668,7 @@ // This redeclaration adds a section attribute. if (New->hasAttr() && !Old->hasAttr()) { if (auto *VD = dyn_cast(New)) { - if (VD->isThisDeclarationADefinition() != VarDecl::Definition) { + if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) { Diag(New->getLocation(), diag::warn_attribute_section_on_redeclaration); Diag(Old->getLocation(), diag::note_previous_declaration); } @@ -2962,6 +3003,9 @@ New->dropAttr(); } + if (CheckRedeclarationModuleOwnership(New, Old)) + return true; + if (!getLangOpts().CPlusPlus) { bool OldOvl = Old->hasAttr(); if (OldOvl != New->hasAttr() && !Old->isImplicit()) { @@ -3537,8 +3581,6 @@ ni = newMethod->param_begin(), ne = newMethod->param_end(); ni != ne && oi != oe; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, *this); - - CheckObjCMethodOverride(newMethod, oldMethod); } static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) { @@ -3831,6 +3873,9 @@ return New->setInvalidDecl(); } + if (CheckRedeclarationModuleOwnership(New, Old)) + return; + // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. // FIXME: The test for external storage here seems wrong? We still @@ -4382,7 +4427,7 @@ SourceLocation NameLoc, bool IsUnion) { LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, - Sema::ForRedeclaration); + Sema::ForVisibleRedeclaration); if (!SemaRef.LookupName(R, S)) return false; // Pick a representative declaration. @@ -5321,7 +5366,7 @@ D.setInvalidType(); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet()) { @@ -5347,8 +5392,10 @@ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) CreateBuiltins = true; - if (IsLinkageLookup) + if (IsLinkageLookup) { Previous.clear(LookupRedeclarationWithLinkage); + Previous.setRedeclarationKind(ForExternalRedeclaration); + } LookupName(Previous, S, CreateBuiltins); } else { // Something like "int foo::x;" @@ -6041,6 +6088,22 @@ diag::warn_dllimport_dropped_from_inline_function) << NewDecl << OldImportAttr; } + + // A specialization of a class template member function is processed here + // since it's a redeclaration. If the parent class is dllexport, the + // specialization inherits that attribute. This doesn't happen automatically + // since the parent class isn't instantiated until later. + if (const CXXMethodDecl *MD = dyn_cast(NewDecl)) { + if (MD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization && + !NewImportAttr && !NewExportAttr) { + if (const DLLExportAttr *ParentExportAttr = + MD->getParent()->getAttr()) { + DLLExportAttr *NewAttr = ParentExportAttr->clone(S.Context); + NewAttr->setInherited(true); + NewDecl->addAttr(NewAttr); + } + } + } } /// Given that we are within the definition of the given function, @@ -6262,7 +6325,7 @@ // The event type cannot be used with the __local, __constant and __global // address space qualifiers. if (R->isEventT()) { - if (R.getAddressSpace()) { + if (R.getAddressSpace() != LangAS::opencl_private) { Diag(D.getLocStart(), diag::err_event_t_addr_space_qual); D.setInvalidType(); } @@ -7096,7 +7159,7 @@ return; LookupResult R(*this, D->getDeclName(), D->getLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); + Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); LookupName(R, S); if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R)) CheckShadow(D, ShadowedDecl, R); @@ -7269,8 +7332,8 @@ // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. // ISO/IEC TR 18037 S5.1.2 - if (!getLangOpts().OpenCL - && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { + if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() && + T.getAddressSpace() != LangAS::Default) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0; NewVD->setInvalidDecl(); return; @@ -7365,7 +7428,7 @@ return; } } - } else if (T.getAddressSpace() != LangAS::Default) { + } else if (T.getAddressSpace() != LangAS::opencl_private) { // Do not allow other address spaces on automatic variable. Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; NewVD->setInvalidDecl(); @@ -7672,7 +7735,7 @@ LookupResult Prev(SemaRef, Name, NewFD->getLocation(), IsLocalFriend ? Sema::LookupLocalFriendName : Sema::LookupOrdinaryName, - Sema::ForRedeclaration); + Sema::ForVisibleRedeclaration); NewFD->setInvalidDecl(); if (IsLocalFriend) @@ -8000,7 +8063,8 @@ if (PointeeType->isPointerType()) return PtrPtrKernelParam; if (PointeeType.getAddressSpace() == LangAS::opencl_generic || - PointeeType.getAddressSpace() == 0) + PointeeType.getAddressSpace() == LangAS::opencl_private || + PointeeType.getAddressSpace() == LangAS::Default) return InvalidAddrSpacePtrKernelParam; return PtrKernelParam; } @@ -8769,10 +8833,8 @@ if (getLangOpts().OpenCL) { // OpenCL v1.1 s6.5: Using an address space qualifier in a function return // type declaration will generate a compilation error. - unsigned AddressSpace = NewFD->getReturnType().getAddressSpace(); - if (AddressSpace == LangAS::opencl_local || - AddressSpace == LangAS::opencl_global || - AddressSpace == LangAS::opencl_constant) { + LangAS AddressSpace = NewFD->getReturnType().getAddressSpace(); + if (AddressSpace != LangAS::Default) { Diag(NewFD->getLocation(), diag::err_opencl_return_value_with_address_space); NewFD->setInvalidDecl(); @@ -11708,7 +11770,7 @@ // Check for redeclaration of parameters, e.g. int foo(int x, int x); if (II) { LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, - ForRedeclaration); + ForVisibleRedeclaration); LookupName(R, S); if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); @@ -11877,13 +11939,13 @@ // duration shall not be qualified by an address-space qualifier." // Since all parameters have automatic store duration, they can not have // an address space. - if (T.getAddressSpace() != 0) { - // OpenCL allows function arguments declared to be an array of a type - // to be qualified with an address space. - if (!(getLangOpts().OpenCL && T->isArrayType())) { - Diag(NameLoc, diag::err_arg_with_address_space); - New->setInvalidDecl(); - } + if (T.getAddressSpace() != LangAS::Default && + // OpenCL allows function arguments declared to be an array of a type + // to be qualified with an address space. + !(getLangOpts().OpenCL && + (T->isArrayType() || T.getAddressSpace() == LangAS::opencl_private))) { + Diag(NameLoc, diag::err_arg_with_address_space); + New->setInvalidDecl(); } return New; @@ -12613,28 +12675,50 @@ /// call, forming a call to an implicitly defined function (per C99 6.5.1p2). NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S) { + Scope *BlockScope = S; + while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent()) + BlockScope = BlockScope->getParent(); + // Before we produce a declaration for an implicitly defined // function, see whether there was a locally-scoped declaration of // this name as a function or variable. If so, use that // (non-visible) declaration, and complain about it. - if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) { - Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev; - Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); - return ExternCPrev; + NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II); + if (ExternCPrev) { + // We still need to inject the function into the enclosing block scope so + // that later (non-call) uses can see it. + PushOnScopeChains(ExternCPrev, BlockScope, /*AddToContext*/false); + + // C89 footnote 38: + // If in fact it is not defined as having type "function returning int", + // the behavior is undefined. + if (!isa(ExternCPrev) || + !Context.typesAreCompatible( + cast(ExternCPrev)->getType(), + Context.getFunctionNoProtoType(Context.IntTy))) { + Diag(Loc, diag::ext_use_out_of_scope_declaration) + << ExternCPrev << !getLangOpts().C99; + Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); + return ExternCPrev; + } } // Extension in C99. Legal in C90, but warn about it. + // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. unsigned diag_id; if (II.getName().startswith("__builtin_")) diag_id = diag::warn_builtin_unknown; - // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. - else if (getLangOpts().OpenCL) - diag_id = diag::err_opencl_implicit_function_decl; - else if (getLangOpts().C99) + else if (getLangOpts().C99 || getLangOpts().OpenCL) diag_id = diag::ext_implicit_function_decl; else diag_id = diag::warn_implicit_function_decl; - Diag(Loc, diag_id) << &II; + Diag(Loc, diag_id) << &II << getLangOpts().OpenCL; + + // If we found a prior declaration of this function, don't bother building + // another one. We've already pushed that one into scope, so there's nothing + // more to do. + if (ExternCPrev) + return ExternCPrev; // Because typo correction is expensive, only do it if the implicit // function declaration is going to be treated as an error. @@ -12687,19 +12771,9 @@ D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. - while (S && !S->isCompoundStmtScope()) - S = S->getParent(); - if (S == nullptr) - S = TUScope; - - DeclContext *PrevDC = CurContext; - CurContext = Context.getTranslationUnitDecl(); - - FunctionDecl *FD = cast(ActOnDeclarator(S, D)); + FunctionDecl *FD = cast(ActOnDeclarator(BlockScope, D)); FD->setImplicit(); - CurContext = PrevDC; - AddKnownFunctionAttributes(FD); return FD; @@ -13256,7 +13330,7 @@ bool isStdBadAlloc = false; bool isStdAlignValT = false; - RedeclarationKind Redecl = ForRedeclaration; + RedeclarationKind Redecl = forRedeclarationInCurContext(); if (TUK == TUK_Friend || TUK == TUK_Reference) Redecl = NotForRedeclaration; @@ -13534,10 +13608,10 @@ // type declared by an elaborated-type-specifier. In C that is not correct // and we should instead merge compatible types found by lookup. if (getLangOpts().CPlusPlus) { - Previous.setRedeclarationKind(ForRedeclaration); + Previous.setRedeclarationKind(forRedeclarationInCurContext()); LookupQualifiedName(Previous, SearchDC); } else { - Previous.setRedeclarationKind(ForRedeclaration); + Previous.setRedeclarationKind(forRedeclarationInCurContext()); LookupName(Previous, S); } } @@ -14035,6 +14109,9 @@ if (!Invalid && SearchDC->isRecord()) SetMemberAccessSpecifier(New, PrevDecl, AS); + if (PrevDecl) + CheckRedeclarationModuleOwnership(New, PrevDecl); + if (TUK == TUK_Definition) New->startDefinition(); @@ -14388,7 +14465,8 @@ // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; - LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); + LookupResult Previous(*this, II, Loc, LookupMemberName, + ForVisibleRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: @@ -14776,7 +14854,7 @@ if (II) { NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, - ForRedeclaration); + ForVisibleRedeclaration); if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -15333,7 +15411,6 @@ if (Enum->isDependentType() || Val->isTypeDependent()) EltTy = Context.DependentTy; else { - SourceLocation ExpLoc; if (getLangOpts().CPlusPlus11 && Enum->isFixed() && !getLangOpts().MSVCCompat) { // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the @@ -15498,7 +15575,7 @@ // determine if we should merge the definition with an existing one and // skip the body. NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); auto *PrevECD = dyn_cast_or_null(PrevDecl); if (!PrevECD) return SkipBodyInfo(); @@ -15529,7 +15606,7 @@ // Verify that there isn't already something declared with this name in this // scope. NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName, - ForRedeclaration); + ForVisibleRedeclaration); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); @@ -15556,8 +15633,7 @@ // enum constant will 'hide' the tag. assert((getLangOpts().CPlusPlus || !isa(PrevDecl)) && "Received TagDecl when not in C++!"); - if (!isa(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) && - shouldLinkPossiblyHiddenDecl(PrevDecl, New)) { + if (!isa(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) { if (isa(PrevDecl)) Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; else @@ -16090,6 +16166,7 @@ // implementation unit. That indicates the 'export' is missing. Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch) << FixItHint::CreateInsertion(ModuleLoc, "export "); + MDK = ModuleDeclKind::Interface; break; case LangOptions::CMK_ModuleMap: @@ -16097,9 +16174,19 @@ return nullptr; } + assert(ModuleScopes.size() == 1 && "expected to be at global module scope"); + // FIXME: Most of this work should be done by the preprocessor rather than // here, in order to support macro import. + // Only one module-declaration is permitted per source file. + if (ModuleScopes.back().Module->Kind == Module::ModuleInterfaceUnit) { + Diag(ModuleLoc, diag::err_module_redeclaration); + Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module), + diag::note_prev_module_declaration); + return nullptr; + } + // Flatten the dots in a module name. Unlike Clang's hierarchical module map // modules, the dots here are just another character that can appear in a // module name. @@ -16110,8 +16197,6 @@ ModuleName += Piece.first->getName(); } - // FIXME: If we've already seen a module-declaration, report an error. - // If a module name was explicitly specified on the command line, it must be // correct. if (!getLangOpts().CurrentModule.empty() && @@ -16126,10 +16211,8 @@ auto &Map = PP.getHeaderSearchInfo().getModuleMap(); Module *Mod; - assert(ModuleScopes.size() == 1 && "expected to be at global module scope"); - switch (MDK) { - case ModuleDeclKind::Module: { + case ModuleDeclKind::Interface: { // We can't have parsed or imported a definition of this module or parsed a // module map defining it already. if (auto *M = Map.findModule(ModuleName)) { @@ -16139,7 +16222,8 @@ else if (const auto *FE = M->getASTFile()) Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file) << FE->getName(); - return nullptr; + Mod = M; + break; } // Create a Module for the module that we're defining. @@ -16158,13 +16242,18 @@ PP.getIdentifierInfo(ModuleName), Path[0].second); Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible, /*IsIncludeDirective=*/false); - if (!Mod) - return nullptr; + if (!Mod) { + Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; + // Create an empty module interface unit for error recovery. + Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName, + ModuleScopes.front().Module); + } break; } // Switch from the global module to the named module. ModuleScopes.back().Module = Mod; + ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation; VisibleModules.setVisible(Mod, ModuleLoc); // From now on, we have an owning module for all declarations we see. @@ -16350,8 +16439,7 @@ // C++ Modules TS draft: // An export-declaration shall appear in the purview of a module other than // the global module. - if (ModuleScopes.empty() || - ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) + if (ModuleScopes.empty() || !ModuleScopes.back().ModuleInterface) Diag(ExportLoc, diag::err_export_not_in_module_interface); // An export-declaration [...] shall not contain more than one diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDeclCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDeclCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDeclCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDeclCXX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -790,7 +790,7 @@ // Check for name conflicts. DeclarationNameInfo NameInfo(B.Name, B.NameLoc); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForRedeclaration); + ForVisibleRedeclaration); LookupName(Previous, S, /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit()); @@ -822,7 +822,8 @@ // is unnamed. DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr, Decomp.getLSquareLoc()); - LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + ForVisibleRedeclaration); // Build the variable that holds the non-decomposed object. bool AddToScope = true; @@ -7895,8 +7896,34 @@ // If we have a virtual destructor, look up the deallocation function if (FunctionDecl *OperatorDelete = FindDeallocationFunctionForDestructor(Loc, RD)) { + Expr *ThisArg = nullptr; + + // If the notional 'delete this' expression requires a non-trivial + // conversion from 'this' to the type of a destroying operator delete's + // first parameter, perform that conversion now. + if (OperatorDelete->isDestroyingOperatorDelete()) { + QualType ParamType = OperatorDelete->getParamDecl(0)->getType(); + if (!declaresSameEntity(ParamType->getAsCXXRecordDecl(), RD)) { + // C++ [class.dtor]p13: + // ... as if for the expression 'delete this' appearing in a + // non-virtual destructor of the destructor's class. + ContextRAII SwitchContext(*this, Destructor); + ExprResult This = + ActOnCXXThis(OperatorDelete->getParamDecl(0)->getLocation()); + assert(!This.isInvalid() && "couldn't form 'this' expr in dtor?"); + This = PerformImplicitConversion(This.get(), ParamType, AA_Passing); + if (This.isInvalid()) { + // FIXME: Register this as a context note so that it comes out + // in the right order. + Diag(Loc, diag::note_implicit_delete_this_in_destructor_here); + return true; + } + ThisArg = This.get(); + } + } + MarkFunctionReferenced(Loc, OperatorDelete); - Destructor->setOperatorDelete(OperatorDelete); + Destructor->setOperatorDelete(OperatorDelete, ThisArg); } } @@ -8465,7 +8492,8 @@ // Since namespace names are unique in their scope, and we don't // look through using directives, just look for any ordinary names // as if by qualified name lookup. - LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration); + LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, + ForExternalRedeclaration); LookupQualifiedName(R, CurContext->getRedeclContext()); NamedDecl *PrevDecl = R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; @@ -9402,7 +9430,7 @@ // Do the redeclaration lookup in the current scope. LookupResult Previous(*this, UsingName, LookupUsingDeclName, - ForRedeclaration); + ForVisibleRedeclaration); Previous.setHideTags(false); if (S) { LookupName(Previous, S); @@ -9982,7 +10010,10 @@ TInfo->getTypeLoc().getBeginLoc()); } - LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + TemplateParamLists.size() + ? forRedeclarationInCurContext() + : ForVisibleRedeclaration); LookupName(Previous, S); // Warn about shadowing the name of a template parameter. @@ -10085,8 +10116,10 @@ if (Invalid) NewDecl->setInvalidDecl(); - else if (OldDecl) + else if (OldDecl) { NewDecl->setPreviousDecl(OldDecl); + CheckRedeclarationModuleOwnership(NewDecl, OldDecl); + } NewND = NewDecl; } else { @@ -10127,7 +10160,7 @@ // Check if we have a previous declaration with the same name. LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, - ForRedeclaration); + ForVisibleRedeclaration); LookupName(PrevR, S); // Check we're not shadowing a template parameter. @@ -10340,7 +10373,7 @@ // implicit special members with this name. DeclarationName Name = FD->getDeclName(); LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName, - ForRedeclaration); + ForExternalRedeclaration); for (auto *D : FD->getParent()->lookup(Name)) if (auto *Acceptable = R.getAcceptableDecl(D)) R.addDecl(Acceptable); @@ -12657,14 +12690,34 @@ if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) return true; + auto *MD = dyn_cast(FnDecl); + + // C++ P0722: + // Within a class C, the first parameter of a destroying operator delete + // shall be of type C *. The first parameter of any other deallocation + // function shall be of type void *. + CanQualType ExpectedFirstParamType = + MD && MD->isDestroyingOperatorDelete() + ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType( + SemaRef.Context.getRecordType(MD->getParent()))) + : SemaRef.Context.VoidPtrTy; + // C++ [basic.stc.dynamic.deallocation]p2: - // Each deallocation function shall return void and its first parameter - // shall be void*. - if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, - SemaRef.Context.VoidPtrTy, - diag::err_operator_delete_dependent_param_type, - diag::err_operator_delete_param_type)) + // Each deallocation function shall return void + if (CheckOperatorNewDeleteTypes( + SemaRef, FnDecl, SemaRef.Context.VoidTy, ExpectedFirstParamType, + diag::err_operator_delete_dependent_param_type, + diag::err_operator_delete_param_type)) + return true; + + // C++ P0722: + // A destroying operator delete shall be a usual deallocation function. + if (MD && !MD->getParent()->isDependentContext() && + MD->isDestroyingOperatorDelete() && !MD->isUsualDeallocationFunction()) { + SemaRef.Diag(MD->getLocation(), + diag::err_destroying_operator_delete_not_usual); return true; + } return false; } @@ -13224,7 +13277,7 @@ IdentifierInfo *II = D.getIdentifier(); if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(), LookupOrdinaryName, - ForRedeclaration)) { + ForVisibleRedeclaration)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration, except for function parameters in // a function-try-block's catch statement. @@ -13673,7 +13726,7 @@ DeclContext *DC; Scope *DCScope = S; LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForRedeclaration); + ForExternalRedeclaration); // There are five cases here. // - There's no scope specifier and we're in a local class. Only look @@ -14858,10 +14911,16 @@ return; } - if (!NoexceptExpr->isValueDependent()) - NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr, - diag::err_noexcept_needs_constant_expression, - /*AllowFold*/ false).get(); + if (!NoexceptExpr->isValueDependent()) { + ExprResult Result = VerifyIntegerConstantExpression( + NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression, + /*AllowFold*/ false); + if (Result.isInvalid()) { + ESI.Type = EST_BasicNoexcept; + return; + } + NoexceptExpr = Result.get(); + } ESI.NoexceptExpr = NoexceptExpr; } return; @@ -14947,7 +15006,8 @@ // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; - LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); + LookupResult Previous(*this, II, Loc, LookupMemberName, + ForVisibleRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDeclObjC.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDeclObjC.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaDeclObjC.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaDeclObjC.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -943,8 +943,9 @@ assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. - NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, - LookupOrdinaryName, ForRedeclaration); + NamedDecl *PrevDecl = + LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, + forRedeclarationInCurContext()); if (PrevDecl && !isa(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; @@ -1095,16 +1096,18 @@ IdentifierInfo *ClassName, SourceLocation ClassLocation) { // Look for previous declaration of alias name - NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation, - LookupOrdinaryName, ForRedeclaration); + NamedDecl *ADecl = + LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName, + forRedeclarationInCurContext()); if (ADecl) { Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; Diag(ADecl->getLocation(), diag::note_previous_declaration); return nullptr; } // Check for class declaration - NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, - LookupOrdinaryName, ForRedeclaration); + NamedDecl *CDeclU = + LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName, + forRedeclarationInCurContext()); if (const TypedefNameDecl *TDecl = dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); @@ -1112,7 +1115,8 @@ if (NamedDecl *IDecl = T->getAs()->getInterface()) { ClassName = IDecl->getIdentifier(); CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, - LookupOrdinaryName, ForRedeclaration); + LookupOrdinaryName, + forRedeclarationInCurContext()); } } } @@ -1174,7 +1178,7 @@ // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc, - ForRedeclaration); + forRedeclarationInCurContext()); ObjCProtocolDecl *PDecl = nullptr; if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) { // If we already have a definition, complain. @@ -1730,7 +1734,7 @@ for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second, - ForRedeclaration); + forRedeclarationInCurContext()); ObjCProtocolDecl *PDecl = ObjCProtocolDecl::Create(Context, CurContext, Ident, IdentPair.second, AtProtocolLoc, @@ -1921,7 +1925,7 @@ // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); if (PrevDecl && !isa(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); @@ -2997,7 +3001,7 @@ // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], - LookupOrdinaryName, ForRedeclaration); + LookupOrdinaryName, forRedeclarationInCurContext()); if (PrevDecl && !isa(PrevDecl)) { // GCC apparently allows the following idiom: // @@ -4219,6 +4223,10 @@ // Then merge the declarations. mergeObjCMethodDecls(ObjCMethod, overridden); + } + + for (ObjCMethodDecl *overridden : overrides) { + CheckObjCMethodOverride(ObjCMethod, overridden); if (ObjCMethod->isImplicit() && overridden->isImplicit()) continue; // Conflicting properties are detected elsewhere. @@ -4443,7 +4451,7 @@ } LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, - LookupOrdinaryName, ForRedeclaration); + LookupOrdinaryName, forRedeclarationInCurContext()); LookupName(R, S); if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); @@ -4680,7 +4688,7 @@ // duration shall not be qualified by an address-space qualifier." // Since all parameters have automatic store duration, they can not have // an address space. - if (T.getAddressSpace() != 0) { + if (T.getAddressSpace() != LangAS::Default) { Diag(IdLoc, diag::err_arg_with_address_space); Invalid = true; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExpr.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExpr.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExpr.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExpr.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -5064,7 +5064,7 @@ } NeedsNewDecl = true; - unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace(); + LangAS AS = ArgType->getPointeeType().getAddressSpace(); QualType PointeeType = ParamType->getPointeeType(); PointeeType = Context.getAddrSpaceQualType(PointeeType, AS); @@ -5760,8 +5760,8 @@ case Type::STK_ObjCObjectPointer: switch (DestTy->getScalarTypeKind()) { case Type::STK_CPointer: { - unsigned SrcAS = SrcTy->getPointeeType().getAddressSpace(); - unsigned DestAS = DestTy->getPointeeType().getAddressSpace(); + LangAS SrcAS = SrcTy->getPointeeType().getAddressSpace(); + LangAS DestAS = DestTy->getPointeeType().getAddressSpace(); if (SrcAS != DestAS) return CK_AddressSpaceConversion; return CK_BitCast; @@ -6365,9 +6365,9 @@ Qualifiers lhQual = lhptee.getQualifiers(); Qualifiers rhQual = rhptee.getQualifiers(); - unsigned ResultAddrSpace = 0; - unsigned LAddrSpace = lhQual.getAddressSpace(); - unsigned RAddrSpace = rhQual.getAddressSpace(); + LangAS ResultAddrSpace = LangAS::Default; + LangAS LAddrSpace = lhQual.getAddressSpace(); + LangAS RAddrSpace = rhQual.getAddressSpace(); if (S.getLangOpts().OpenCL) { // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address // spaces is disallowed. @@ -7649,8 +7649,8 @@ if (const PointerType *LHSPointer = dyn_cast(LHSType)) { // U* -> T* if (isa(RHSType)) { - unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); - unsigned AddrSpaceR = RHSType->getPointeeType().getAddressSpace(); + LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); + LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace(); Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return checkPointerTypesForAssignment(*this, LHSType, RHSType); } @@ -7685,10 +7685,10 @@ // U^ -> void* if (RHSType->getAs()) { if (LHSPointer->getPointeeType()->isVoidType()) { - unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); - unsigned AddrSpaceR = RHSType->getAs() - ->getPointeeType() - .getAddressSpace(); + LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); + LangAS AddrSpaceR = RHSType->getAs() + ->getPointeeType() + .getAddressSpace(); Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return Compatible; @@ -7702,12 +7702,12 @@ if (isa(LHSType)) { // U^ -> T^ if (RHSType->isBlockPointerType()) { - unsigned AddrSpaceL = LHSType->getAs() - ->getPointeeType() - .getAddressSpace(); - unsigned AddrSpaceR = RHSType->getAs() - ->getPointeeType() - .getAddressSpace(); + LangAS AddrSpaceL = LHSType->getAs() + ->getPointeeType() + .getAddressSpace(); + LangAS AddrSpaceR = RHSType->getAs() + ->getPointeeType() + .getAddressSpace(); Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType); } @@ -9804,8 +9804,8 @@ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); } } - unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace(); - unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace(); + LangAS AddrSpaceL = LCanPointeeTy.getAddressSpace(); + LangAS AddrSpaceR = RCanPointeeTy.getAddressSpace(); CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; if (LHSIsNull && !RHSIsNull) @@ -14893,7 +14893,8 @@ IsVariableAConstantExpression(Var, SemaRef.Context)) { // A reference initialized by a constant expression can never be // odr-used, so simply ignore it. - if (!Var->getType()->isReferenceType()) + if (!Var->getType()->isReferenceType() || + (SemaRef.LangOpts.OpenMP && SemaRef.IsOpenMPCapturedDecl(Var))) SemaRef.MaybeODRUseExprs.insert(E); } else if (OdrUseContext) { MarkVarDeclODRUsed(Var, Loc, SemaRef, diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExprCXX.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExprCXX.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExprCXX.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExprCXX.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1407,14 +1407,20 @@ UsualDeallocFnInfo() : Found(), FD(nullptr) {} UsualDeallocFnInfo(Sema &S, DeclAccessPair Found) : Found(Found), FD(dyn_cast(Found->getUnderlyingDecl())), - HasSizeT(false), HasAlignValT(false), CUDAPref(Sema::CFP_Native) { + Destroying(false), HasSizeT(false), HasAlignValT(false), + CUDAPref(Sema::CFP_Native) { // A function template declaration is never a usual deallocation function. if (!FD) return; - if (FD->getNumParams() == 3) + unsigned NumBaseParams = 1; + if (FD->isDestroyingOperatorDelete()) { + Destroying = true; + ++NumBaseParams; + } + if (FD->getNumParams() == NumBaseParams + 2) HasAlignValT = HasSizeT = true; - else if (FD->getNumParams() == 2) { - HasSizeT = FD->getParamDecl(1)->getType()->isIntegerType(); + else if (FD->getNumParams() == NumBaseParams + 1) { + HasSizeT = FD->getParamDecl(NumBaseParams)->getType()->isIntegerType(); HasAlignValT = !HasSizeT; } @@ -1428,6 +1434,12 @@ bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize, bool WantAlign) const { + // C++ P0722: + // A destroying operator delete is preferred over a non-destroying + // operator delete. + if (Destroying != Other.Destroying) + return Destroying; + // C++17 [expr.delete]p10: // If the type has new-extended alignment, a function with a parameter // of type std::align_val_t is preferred; otherwise a function without @@ -1444,7 +1456,7 @@ DeclAccessPair Found; FunctionDecl *FD; - bool HasSizeT, HasAlignValT; + bool Destroying, HasSizeT, HasAlignValT; Sema::CUDAFunctionPreference CUDAPref; }; } @@ -2101,7 +2113,7 @@ else if (AllocType->isVariablyModifiedType()) return Diag(Loc, diag::err_variably_modified_new_type) << AllocType; - else if (AllocType.getAddressSpace()) + else if (AllocType.getAddressSpace() != LangAS::Default) return Diag(Loc, diag::err_address_space_qualified_new) << AllocType.getUnqualifiedType() << AllocType.getQualifiers().getAddressSpaceAttributePrintValue(); @@ -3173,7 +3185,7 @@ QualType Pointee = Type->getAs()->getPointeeType(); QualType PointeeElem = Context.getBaseElementType(Pointee); - if (Pointee.getAddressSpace()) + if (Pointee.getAddressSpace() != LangAS::Default) return Diag(Ex.get()->getLocStart(), diag::err_address_space_qualified_delete) << Pointee.getUnqualifiedType() @@ -3261,16 +3273,30 @@ MarkFunctionReferenced(StartLoc, OperatorDelete); - // Check access and ambiguity of operator delete and destructor. + // Check access and ambiguity of destructor if we're going to call it. + // Note that this is required even for a virtual delete. + bool IsVirtualDelete = false; if (PointeeRD) { if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { - CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, - PDiag(diag::err_access_dtor) << PointeeElem); + CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, + PDiag(diag::err_access_dtor) << PointeeElem); + IsVirtualDelete = Dtor->isVirtual(); } } diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this); + + // Convert the operand to the type of the first parameter of operator + // delete. This is only necessary if we selected a destroying operator + // delete that we are going to call (non-virtually); converting to void* + // is trivial and left to AST consumers to handle. + QualType ParamType = OperatorDelete->getParamDecl(0)->getType(); + if (!IsVirtualDelete && !ParamType->getPointeeType()->isVoidType()) { + Ex = PerformImplicitConversion(Ex.get(), ParamType, AA_Passing); + if (Ex.isInvalid()) + return ExprError(); + } } CXXDeleteExpr *Result = new (Context) CXXDeleteExpr( @@ -4798,9 +4824,13 @@ } case BTT_IsSame: return Self.Context.hasSameType(LhsT, RhsT); - case BTT_TypeCompatible: - return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(), - RhsT.getUnqualifiedType()); + case BTT_TypeCompatible: { + // GCC ignores cv-qualifiers on arrays for this builtin. + Qualifiers LhsQuals, RhsQuals; + QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(LhsT, LhsQuals); + QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals); + return Self.Context.typesAreCompatible(Lhs, Rhs); + } case BTT_IsConvertible: case BTT_IsConvertibleTo: { // C++0x [meta.rel]p4: diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExprMember.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExprMember.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExprMember.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExprMember.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -693,8 +693,7 @@ Sema::RedeclarationKind Redecl; }; QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), - R.isForRedeclaration() ? Sema::ForRedeclaration - : Sema::NotForRedeclaration}; + R.redeclarationKind()}; TE = SemaRef.CorrectTypoDelayed( R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, llvm::make_unique(RTy), diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExprObjC.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExprObjC.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaExprObjC.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaExprObjC.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -4317,14 +4317,37 @@ /// Look for an ObjCReclaimReturnedObject cast and destroy it. static Expr *maybeUndoReclaimObject(Expr *e) { - // For now, we just undo operands that are *immediately* reclaim - // expressions, which prevents the vast majority of potential - // problems here. To catch them all, we'd need to rebuild arbitrary - // value-propagating subexpressions --- we can't reliably rebuild - // in-place because of expression sharing. - if (auto *ice = dyn_cast(e->IgnoreParens())) - if (ice->getCastKind() == CK_ARCReclaimReturnedObject) - return ice->getSubExpr(); + Expr *curExpr = e, *prevExpr = nullptr; + + // Walk down the expression until we hit an implicit cast of kind + // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast. + while (true) { + if (auto *pe = dyn_cast(curExpr)) { + prevExpr = curExpr; + curExpr = pe->getSubExpr(); + continue; + } + + if (auto *ce = dyn_cast(curExpr)) { + if (auto *ice = dyn_cast(ce)) + if (ice->getCastKind() == CK_ARCReclaimReturnedObject) { + if (!prevExpr) + return ice->getSubExpr(); + if (auto *pe = dyn_cast(prevExpr)) + pe->setSubExpr(ice->getSubExpr()); + else + cast(prevExpr)->setSubExpr(ice->getSubExpr()); + return e; + } + + prevExpr = curExpr; + curExpr = ce->getSubExpr(); + continue; + } + + // Break out of the loop if curExpr is neither a Paren nor a Cast. + break; + } return e; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaInit.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaInit.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaInit.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaInit.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -826,6 +826,34 @@ return InitializableMembers - structDecl->hasFlexibleArrayMember(); } +/// Determine whether Entity is an entity for which it is idiomatic to elide +/// the braces in aggregate initialization. +static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) { + // Recursive initialization of the one and only field within an aggregate + // class is considered idiomatic. This case arises in particular for + // initialization of std::array, where the C++ standard suggests the idiom of + // + // std::array arr = {1, 2, 3}; + // + // (where std::array is an aggregate struct containing a single array field. + + // FIXME: Should aggregate initialization of a struct with a single + // base class and no members also suppress the warning? + if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent()) + return false; + + auto *ParentRD = + Entity.getParent()->getType()->castAs()->getDecl(); + if (CXXRecordDecl *CXXRD = dyn_cast(ParentRD)) + if (CXXRD->getNumBases()) + return false; + + auto FieldIt = ParentRD->field_begin(); + assert(FieldIt != ParentRD->field_end() && + "no fields but have initializer for member?"); + return ++FieldIt == ParentRD->field_end(); +} + /// Check whether the range of the initializer \p ParentIList from element /// \p Index onwards can be used to initialize an object of type \p T. Update /// \p Index to indicate how many elements of the list were consumed. @@ -887,7 +915,8 @@ // Complain about missing braces. if ((T->isArrayType() || T->isRecordType()) && - !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts())) { + !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) && + !isIdiomaticBraceElisionEntity(Entity)) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), diag::warn_missing_braces) << StructuredSubobjectInitList->getSourceRange() diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaLookup.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaLookup.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaLookup.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaLookup.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -88,13 +88,15 @@ /// A collection of using directives, as used by C++ unqualified /// lookup. class UnqualUsingDirectiveSet { + Sema &SemaRef; + typedef SmallVector ListTy; ListTy list; llvm::SmallPtrSet visited; public: - UnqualUsingDirectiveSet() {} + UnqualUsingDirectiveSet(Sema &SemaRef) : SemaRef(SemaRef) {} void visitScopeChain(Scope *S, Scope *InnermostFileScope) { // C++ [namespace.udir]p1: @@ -113,7 +115,8 @@ visit(Ctx, Ctx); } else if (!Ctx || Ctx->isFunctionOrMethod()) { for (auto *I : S->using_directives()) - visit(I, InnermostFileDC); + if (SemaRef.isVisible(I)) + visit(I, InnermostFileDC); } } } @@ -152,7 +155,7 @@ while (true) { for (auto UD : DC->using_directives()) { DeclContext *NS = UD->getNominatedNamespace(); - if (visited.insert(NS).second) { + if (visited.insert(NS).second && SemaRef.isVisible(UD)) { addUsingDirective(UD, EffectiveDC); queue.push_back(NS); } @@ -1085,7 +1088,7 @@ // } // } // - UnqualUsingDirectiveSet UDirs; + UnqualUsingDirectiveSet UDirs(*this); bool VisitedUsingDirectives = false; bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = nullptr; @@ -1609,11 +1612,39 @@ } bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) { + // FIXME: If there are both visible and hidden declarations, we need to take + // into account whether redeclaration is possible. Example: + // + // Non-imported module: + // int f(T); // #1 + // Some TU: + // static int f(U); // #2, not a redeclaration of #1 + // int f(T); // #3, finds both, should link with #1 if T != U, but + // // with #2 if T == U; neither should be ambiguous. for (auto *D : R) { if (isVisible(D)) return true; + assert(D->isExternallyDeclarable() && + "should not have hidden, non-externally-declarable result here"); } - return New->isExternallyVisible(); + + // This function is called once "New" is essentially complete, but before a + // previous declaration is attached. We can't query the linkage of "New" in + // general, because attaching the previous declaration can change the + // linkage of New to match the previous declaration. + // + // However, because we've just determined that there is no *visible* prior + // declaration, we can compute the linkage here. There are two possibilities: + // + // * This is not a redeclaration; it's safe to compute the linkage now. + // + // * This is a redeclaration of a prior declaration that is externally + // redeclarable. In that case, the linkage of the declaration is not + // changed by attaching the prior declaration, because both are externally + // declarable (and thus ExternalLinkage or VisibleNoLinkage). + // + // FIXME: This is subtle and fragile. + return New->isExternallyDeclarable(); } /// \brief Retrieve the visible declaration corresponding to D, if any. @@ -1840,22 +1871,19 @@ DeclContext *StartDC) { assert(StartDC->isFileContext() && "start context is not a file context"); - DeclContext::udir_range UsingDirectives = StartDC->using_directives(); - if (UsingDirectives.begin() == UsingDirectives.end()) return false; + // We have not yet looked into these namespaces, much less added + // their "using-children" to the queue. + SmallVector Queue; // We have at least added all these contexts to the queue. llvm::SmallPtrSet Visited; Visited.insert(StartDC); - // We have not yet looked into these namespaces, much less added - // their "using-children" to the queue. - SmallVector Queue; - // We have already looked into the initial namespace; seed the queue // with its using-children. - for (auto *I : UsingDirectives) { + for (auto *I : StartDC->using_directives()) { NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace(); - if (Visited.insert(ND).second) + if (Visited.insert(ND).second && S.isVisible(I)) Queue.push_back(ND); } @@ -1903,7 +1931,7 @@ for (auto I : ND->using_directives()) { NamespaceDecl *Nom = I->getNominatedNamespace(); - if (Visited.insert(Nom).second) + if (Visited.insert(Nom).second && S.isVisible(I)) Queue.push_back(Nom); } } @@ -3321,16 +3349,24 @@ continue; } - if (isa(D)) - D = cast(D)->getTargetDecl(); + auto *Underlying = D; + if (auto *USD = dyn_cast(D)) + Underlying = USD->getTargetDecl(); - if (!isa(D) && !isa(D)) + if (!isa(Underlying) && + !isa(Underlying)) continue; - if (!isVisible(D) && !(D = findAcceptableDecl(*this, D))) - continue; + if (!isVisible(D)) { + D = findAcceptableDecl(*this, D); + if (!D) + continue; + if (auto *USD = dyn_cast(D)) + Underlying = USD->getTargetDecl(); + } - Result.insert(D); + // FIXME: Preserve D as the FoundDecl. + Result.insert(Underlying); } } } @@ -3512,6 +3548,8 @@ if (QualifiedNameLookup) { ShadowContextRAII Shadow(Visited); for (auto I : Ctx->using_directives()) { + if (!Result.getSema().isVisible(I)) + continue; LookupVisibleDecls(I->getNominatedNamespace(), Result, QualifiedNameLookup, InBaseClass, Consumer, Visited, IncludeDependentBases); @@ -3639,8 +3677,10 @@ !Visited.alreadyVisitedContext(S->getEntity())) || (S->getEntity())->isFunctionOrMethod()) { FindLocalExternScope FindLocals(Result); - // Walk through the declarations in this Scope. - for (auto *D : S->decls()) { + // Walk through the declarations in this Scope. The consumer might add new + // decls to the scope as part of deserialization, so make a copy first. + SmallVector ScopeDecls(S->decls().begin(), S->decls().end()); + for (Decl *D : ScopeDecls) { if (NamedDecl *ND = dyn_cast(D)) if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), nullptr, false); @@ -3718,7 +3758,7 @@ // Determine the set of using directives available during // unqualified name lookup. Scope *Initial = S; - UnqualUsingDirectiveSet UDirs; + UnqualUsingDirectiveSet UDirs(*this); if (getLangOpts().CPlusPlus) { // Find the first namespace or translation-unit scope. while (S && !isNamespaceOrTranslationUnitScope(S)) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaObjCProperty.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaObjCProperty.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaObjCProperty.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaObjCProperty.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1599,7 +1599,11 @@ // meaningless for readonly properties, so don't diagnose if the // atomic property is 'readonly'. checkAtomicPropertyMismatch(*this, SuperProperty, Property, false); - if (Property->getSetterName() != SuperProperty->getSetterName()) { + // Readonly properties from protocols can be implemented as "readwrite" + // with a custom setter name. + if (Property->getSetterName() != SuperProperty->getSetterName() && + !(SuperProperty->isReadOnly() && + isa(SuperProperty->getDeclContext()))) { Diag(Property->getLocation(), diag::warn_property_attribute) << Property->getDeclName() << "setter" << inheritedName; Diag(SuperProperty->getLocation(), diag::note_property_declare); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaOpenMP.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaOpenMP.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaOpenMP.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaOpenMP.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -45,7 +45,13 @@ enum DefaultDataSharingAttributes { DSA_unspecified = 0, /// \brief Data sharing attribute not specified. DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'. - DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'. + DSA_shared = 1 << 1, /// \brief Default data sharing attribute 'shared'. +}; + +/// Attributes of the defaultmap clause. +enum DefaultMapAttributes { + DMA_unspecified, /// Default mapping is not specified. + DMA_tofrom_scalar, /// Default mapping is 'tofrom:scalar'. }; /// \brief Stack for tracking declarations used in OpenMP directives and @@ -115,6 +121,8 @@ LoopControlVariablesMapTy LCVMap; DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; SourceLocation DefaultAttrLoc; + DefaultMapAttributes DefaultMapAttr = DMA_unspecified; + SourceLocation DefaultMapAttrLoc; OpenMPDirectiveKind Directive = OMPD_unknown; DeclarationNameInfo DirectiveName; Scope *CurScope = nullptr; @@ -341,6 +349,12 @@ Stack.back().first.back().DefaultAttr = DSA_shared; Stack.back().first.back().DefaultAttrLoc = Loc; } + /// Set default data mapping attribute to 'tofrom:scalar'. + void setDefaultDMAToFromScalar(SourceLocation Loc) { + assert(!isStackEmpty()); + Stack.back().first.back().DefaultMapAttr = DMA_tofrom_scalar; + Stack.back().first.back().DefaultMapAttrLoc = Loc; + } DefaultDataSharingAttributes getDefaultDSA() const { return isStackEmpty() ? DSA_unspecified @@ -350,6 +364,17 @@ return isStackEmpty() ? SourceLocation() : Stack.back().first.back().DefaultAttrLoc; } + DefaultMapAttributes getDefaultDMA() const { + return isStackEmpty() ? DMA_unspecified + : Stack.back().first.back().DefaultMapAttr; + } + DefaultMapAttributes getDefaultDMAAtLevel(unsigned Level) const { + return Stack.back().first[Level].DefaultMapAttr; + } + SourceLocation getDefaultDMALocation() const { + return isStackEmpty() ? SourceLocation() + : Stack.back().first.back().DefaultMapAttrLoc; + } /// \brief Checks if the specified variable is a threadprivate. bool isThreadPrivate(VarDecl *D) { @@ -1242,7 +1267,8 @@ IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection); } else { // By default, all the data that has a scalar type is mapped by copy. - IsByRef = !Ty->isScalarType(); + IsByRef = !Ty->isScalarType() || + DSAStack->getDefaultDMAAtLevel(Level) == DMA_tofrom_scalar; } } @@ -1804,7 +1830,7 @@ if (auto *VD = dyn_cast(E->getDecl())) { VD = VD->getCanonicalDecl(); // Skip internally declared variables. - if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) + if (VD->hasLocalStorage() && !CS->capturesVariable(VD)) return; auto DVar = Stack->getTopDSA(VD, false); @@ -1812,6 +1838,10 @@ if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second) return; + // Skip internally declared static variables. + if (VD->hasGlobalStorage() && !CS->capturesVariable(VD)) + return; + auto ELoc = E->getExprLoc(); auto DKind = Stack->getCurrentDirective(); // The default(none) clause requires that each variable that is referenced @@ -1848,20 +1878,16 @@ MC.getAssociatedExpression())); }); })) { - bool CapturedByCopy = false; + bool IsFirstprivate = false; // By default lambdas are captured as firstprivates. if (const auto *RD = VD->getType().getNonReferenceType()->getAsCXXRecordDecl()) - if (RD->isLambda()) - CapturedByCopy = true; - CapturedByCopy = - CapturedByCopy || - llvm::any_of( - CS->captures(), [VD](const CapturedStmt::Capture &I) { - return I.capturesVariableByCopy() && - I.getCapturedVar()->getCanonicalDecl() == VD; - }); - if (CapturedByCopy) + IsFirstprivate = RD->isLambda(); + IsFirstprivate = + IsFirstprivate || + (VD->getType().getNonReferenceType()->isScalarType() && + Stack->getDefaultDMA() != DMA_tofrom_scalar); + if (IsFirstprivate) ImplicitFirstprivate.emplace_back(E); else ImplicitMap.emplace_back(E); @@ -2043,7 +2069,8 @@ case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_sections: - case OMPD_teams: { + case OMPD_teams: + case OMPD_teams_distribute: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); @@ -2166,7 +2193,6 @@ case OMPD_distribute_parallel_for_simd: case OMPD_distribute_simd: case OMPD_distribute_parallel_for: - case OMPD_teams_distribute: case OMPD_teams_distribute_simd: case OMPD_teams_distribute_parallel_for_simd: case OMPD_teams_distribute_parallel_for: @@ -11513,7 +11539,7 @@ Decls.reserve(ReductionTypes.size()); LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName, - ForRedeclaration); + forRedeclarationInCurContext()); // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions // A reduction-identifier may not be re-declared in the current scope for the // same type or for a type that is compatible according to the base language @@ -11905,6 +11931,7 @@ << Value << getOpenMPClauseName(OMPC_defaultmap); return nullptr; } + DSAStack->setDefaultDMAToFromScalar(StartLoc); return new (Context) OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaOverload.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaOverload.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaOverload.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaOverload.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -11927,7 +11927,7 @@ ExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *Input) { + Expr *Input, bool PerformADL) { OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc); assert(Op != OO_None && "Invalid opcode for overloaded unary operator"); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); @@ -11978,9 +11978,11 @@ AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); // Add candidates from ADL. - AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray, - /*ExplicitTemplateArgs*/nullptr, - CandidateSet); + if (PerformADL) { + AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray, + /*ExplicitTemplateArgs*/nullptr, + CandidateSet); + } // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -12118,7 +12120,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS) { + Expr *LHS, Expr *RHS, bool PerformADL) { Expr *Args[2] = { LHS, RHS }; LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple @@ -12149,7 +12151,7 @@ UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/ true, IsOverloaded(Fns), + /*ADL*/PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end()); return new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy, @@ -12192,7 +12194,7 @@ // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not // performed for an assignment operator (nor for operator[] nor operator->, // which don't get here). - if (Opc != BO_Assign) + if (Opc != BO_Assign && PerformADL) AddArgumentDependentLookupCandidates(OpName, OpLoc, Args, /*ExplicitTemplateArgs*/ nullptr, CandidateSet); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaTemplate.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaTemplate.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaTemplate.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaTemplate.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -778,7 +778,7 @@ SourceLocation Loc, IdentifierInfo *Name) { NamedDecl *PrevDecl = SemaRef.LookupSingleName( - S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForRedeclaration); + S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); if (PrevDecl && PrevDecl->isTemplateParameter()) SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl); } @@ -1133,7 +1133,7 @@ LookupResult Previous(*this, Name, NameLoc, (SS.isEmpty() && TUK == TUK_Friend) ? LookupTagName : LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); if (SS.isNotEmpty() && !SS.isInvalid()) { SemanticContext = computeDeclContext(SS, true); if (!SemanticContext) { @@ -1192,8 +1192,8 @@ // If there is a previous declaration with the same name, check // whether this is a valid redeclaration. - ClassTemplateDecl *PrevClassTemplate - = dyn_cast_or_null(PrevDecl); + ClassTemplateDecl *PrevClassTemplate = + dyn_cast_or_null(PrevDecl); // We may have found the injected-class-name of a class template, // class template partial specialization, or class template specialization. @@ -1484,6 +1484,9 @@ CurContext->addDecl(Friend); } + if (PrevClassTemplate) + CheckRedeclarationModuleOwnership(NewTemplate, PrevClassTemplate); + if (Invalid) { NewTemplate->setInvalidDecl(); NewClass->setInvalidDecl(); @@ -3677,7 +3680,7 @@ // Check that this isn't a redefinition of this specialization, // merging with previous declarations. LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); PrevSpec.addDecl(PrevDecl); D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec)); } else if (Specialization->isStaticDataMember() && @@ -6166,7 +6169,6 @@ // -- an integral constant-expression of integral or enumeration // type; or // -- the name of a non-type template-parameter; or - SourceLocation NonConstantLoc; llvm::APSInt Value; if (!ArgType->isIntegralOrEnumerationType()) { Diag(Arg->getLocStart(), diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaTemplateDeduction.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaTemplateDeduction.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaTemplateDeduction.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaTemplateDeduction.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1870,11 +1870,10 @@ Deduced); } - if (Arg.getAddressSpace() >= LangAS::FirstTargetAddressSpace) { + if (isTargetAddressSpace(Arg.getAddressSpace())) { llvm::APSInt ArgAddressSpace(S.Context.getTypeSize(S.Context.IntTy), false); - ArgAddressSpace = - (Arg.getAddressSpace() - LangAS::FirstTargetAddressSpace); + ArgAddressSpace = toTargetAddressSpace(Arg.getAddressSpace()); // Perform deduction on the pointer types. if (Sema::TemplateDeductionResult Result = diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1195,7 +1195,8 @@ // Look for a previous declaration of the template in the owning // context. LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); + Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); SemaRef.LookupQualifiedName(R, DC); if (R.isSingleResult()) { @@ -1685,7 +1686,6 @@ Params[P]->setOwningFunction(Function); Function->setParams(Params); - SourceLocation InstantiateAtPOI; if (TemplateParams) { // Our resulting instantiation is actually a function template, since we // are substituting only the outer template parameters. For example, given @@ -1736,7 +1736,8 @@ SemaRef, Function->getDeclName(), SourceLocation(), D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage : Sema::LookupOrdinaryName, - Sema::ForRedeclaration); + D->isLocalExternDecl() ? Sema::ForExternalRedeclaration + : SemaRef.forRedeclarationInCurContext()); if (DependentFunctionTemplateSpecializationInfo *Info = D->getDependentSpecializationInfo()) { @@ -2054,7 +2055,7 @@ Method->setInvalidDecl(); LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, - Sema::ForRedeclaration); + Sema::ForExternalRedeclaration); if (!FunctionTemplate || TemplateParams || isFriend) { SemaRef.LookupQualifiedName(Previous, Record); @@ -2493,7 +2494,7 @@ bool CheckRedeclaration = Owner->isRecord(); LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName, - Sema::ForRedeclaration); + Sema::ForVisibleRedeclaration); UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(), @@ -2712,7 +2713,7 @@ return nullptr; LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, - Sema::ForRedeclaration); + Sema::ForExternalRedeclaration); TemplateArgumentListInfo TemplateArgs; TemplateArgumentListInfo *TemplateArgsPtr = nullptr; @@ -4075,7 +4076,8 @@ *this, NewVar->getDeclName(), NewVar->getLocation(), NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage : Sema::LookupOrdinaryName, - Sema::ForRedeclaration); + NewVar->isLocalExternDecl() ? Sema::ForExternalRedeclaration + : forRedeclarationInCurContext()); if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() && (!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() || @@ -4433,7 +4435,7 @@ // Merge the definition with the declaration. LookupResult R(*this, Var->getDeclName(), Var->getLocation(), - LookupOrdinaryName, ForRedeclaration); + LookupOrdinaryName, forRedeclarationInCurContext()); R.addDecl(OldVar); MergeVarDecl(Var, R); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaType.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaType.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/SemaType.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/SemaType.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -4460,7 +4460,8 @@ FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); - if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) { + if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus + && !LangOpts.OpenCL) { // Simple void foo(), where the incoming T is the result type. T = Context.getFunctionNoProtoType(T, EI); } else { @@ -4937,7 +4938,6 @@ TypeSourceInfo *ReturnTypeInfo = nullptr; QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo); - if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount) inferARCWriteback(state, T); @@ -5631,7 +5631,7 @@ // If this type is already address space qualified, reject it. // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified // by qualifiers for two or more different address spaces." - if (T.getAddressSpace()) { + if (T.getAddressSpace() != LangAS::Default) { Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); return QualType(); } @@ -5655,15 +5655,16 @@ } llvm::APSInt max(addrSpace.getBitWidth()); - max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace; + max = + Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace; if (addrSpace > max) { Diag(AttrLoc, diag::err_attribute_address_space_too_high) << (unsigned)max.getZExtValue() << AddrSpace->getSourceRange(); return QualType(); } - unsigned ASIdx = static_cast(addrSpace.getZExtValue()) + - LangAS::FirstTargetAddressSpace; + LangAS ASIdx = + getLangASFromTargetAS(static_cast(addrSpace.getZExtValue())); return Context.getAddrSpaceQualType(T, ASIdx); } @@ -5689,7 +5690,7 @@ // If this type is already address space qualified, reject it. // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by // qualifiers for two or more different address spaces." - if (Type.getAddressSpace()) { + if (Type.getAddressSpace() != LangAS::Default) { S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); Attr.setInvalid(); return; @@ -5703,7 +5704,7 @@ return; } - unsigned ASIdx; + LangAS ASIdx; if (Attr.getKind() == AttributeList::AT_AddressSpace) { // Check the attribute arguments. @@ -5751,9 +5752,10 @@ ASIdx = LangAS::opencl_constant; break; case AttributeList::AT_OpenCLGenericAddressSpace: ASIdx = LangAS::opencl_generic; break; + case AttributeList::AT_OpenCLPrivateAddressSpace: + ASIdx = LangAS::opencl_private; break; default: - assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace); - ASIdx = 0; break; + llvm_unreachable("Invalid address space"); } Type = S.Context.getAddrSpaceQualType(Type, ASIdx); @@ -6985,6 +6987,92 @@ } } +static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, + QualType &T, TypeAttrLocation TAL) { + Declarator &D = State.getDeclarator(); + + // Handle the cases where address space should not be deduced. + // + // The pointee type of a pointer type is alwasy deduced since a pointer always + // points to some memory location which should has an address space. + // + // There are situations that at the point of certain declarations, the address + // space may be unknown and better to be left as default. For example, when + // definining a typedef or struct type, they are not associated with any + // specific address space. Later on, they may be used with any address space + // to declare a variable. + // + // The return value of a function is r-value, therefore should not have + // address space. + // + // The void type does not occupy memory, therefore should not have address + // space, except when it is used as a pointee type. + // + // Since LLVM assumes function type is in default address space, it should not + // have address space. + auto ChunkIndex = State.getCurrentChunkIndex(); + bool IsPointee = + ChunkIndex > 0 && + (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer || + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer); + bool IsFuncReturnType = + ChunkIndex > 0 && + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function; + bool IsFuncType = + ChunkIndex < D.getNumTypeObjects() && + D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function; + if ( // Do not deduce addr space for function return type and function type, + // otherwise it will fail some sema check. + IsFuncReturnType || IsFuncType || + // Do not deduce addr space for member types of struct, except the pointee + // type of a pointer member type. + (D.getContext() == Declarator::MemberContext && !IsPointee) || + // Do not deduce addr space for types used to define a typedef and the + // typedef itself, except the pointee type of a pointer type which is used + // to define the typedef. + (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef && + !IsPointee) || + // Do not deduce addr space of the void type, e.g. in f(void), otherwise + // it will fail some sema check. + (T->isVoidType() && !IsPointee)) + return; + + LangAS ImpAddr; + // Put OpenCL automatic variable in private address space. + // OpenCL v1.2 s6.5: + // The default address space name for arguments to a function in a + // program, or local variables of a function is __private. All function + // arguments shall be in the __private address space. + if (State.getSema().getLangOpts().OpenCLVersion <= 120) { + ImpAddr = LangAS::opencl_private; + } else { + // If address space is not set, OpenCL 2.0 defines non private default + // address spaces for some cases: + // OpenCL 2.0, section 6.5: + // The address space for a variable at program scope or a static variable + // inside a function can either be __global or __constant, but defaults to + // __global if not specified. + // (...) + // Pointers that are declared without pointing to a named address space + // point to the generic address space. + if (IsPointee) { + ImpAddr = LangAS::opencl_generic; + } else { + if (D.getContext() == Declarator::FileContext) { + ImpAddr = LangAS::opencl_global; + } else { + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) { + ImpAddr = LangAS::opencl_global; + } else { + ImpAddr = LangAS::opencl_private; + } + } + } + } + T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr); +} + static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, AttributeList *attrs) { // Scan through and apply attributes to this type where it makes sense. Some @@ -6992,7 +7080,6 @@ // type, but others can be present in the type specifiers even though they // apply to the decl. Here we apply type attributes and ignore the rest. - bool hasOpenCLAddressSpace = false; while (attrs) { AttributeList &attr = *attrs; attrs = attr.getNext(); // reset to the next here due to early loop continue @@ -7055,7 +7142,6 @@ case AttributeList::AT_AddressSpace: HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); - hasOpenCLAddressSpace = true; break; OBJC_POINTER_TYPE_ATTRS_CASELIST: if (!handleObjCPointerTypeAttr(state, attr, type)) @@ -7156,39 +7242,11 @@ } } - // If address space is not set, OpenCL 2.0 defines non private default - // address spaces for some cases: - // OpenCL 2.0, section 6.5: - // The address space for a variable at program scope or a static variable - // inside a function can either be __global or __constant, but defaults to - // __global if not specified. - // (...) - // Pointers that are declared without pointing to a named address space point - // to the generic address space. - if (state.getSema().getLangOpts().OpenCLVersion >= 200 && - !hasOpenCLAddressSpace && type.getAddressSpace() == 0 && - (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) { - Declarator &D = state.getDeclarator(); - if (state.getCurrentChunkIndex() > 0 && - (D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind == - DeclaratorChunk::Pointer || - D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind == - DeclaratorChunk::BlockPointer)) { - type = state.getSema().Context.getAddrSpaceQualType( - type, LangAS::opencl_generic); - } else if (state.getCurrentChunkIndex() == 0 && - D.getContext() == Declarator::FileContext && - !D.isFunctionDeclarator() && !D.isFunctionDefinition() && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && - !type->isSamplerT()) - type = state.getSema().Context.getAddrSpaceQualType( - type, LangAS::opencl_global); - else if (state.getCurrentChunkIndex() == 0 && - D.getContext() == Declarator::BlockContext && - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) - type = state.getSema().Context.getAddrSpaceQualType( - type, LangAS::opencl_global); - } + if (!state.getSema().getLangOpts().OpenCL || + type.getAddressSpace() != LangAS::Default) + return; + + deduceOpenCLImplicitAddrSpace(state, type, TAL); } void Sema::completeExprArrayBound(Expr *E) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/TreeTransform.h llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/TreeTransform.h --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Sema/TreeTransform.h 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Sema/TreeTransform.h 2017-10-17 14:41:55.000000000 +0000 @@ -4199,7 +4199,6 @@ TypeLoc TL = DI->getTypeLoc(); TLB.reserve(TL.getFullDataSize()); - Qualifiers Quals; auto QTL = TL.getAs(); if (QTL) TL = QTL.getUnqualifiedLoc(); @@ -12636,10 +12635,14 @@ // Compute the transformed set of functions (and function templates) to be // used during overload resolution. UnresolvedSet<16> Functions; + bool RequiresADL; if (UnresolvedLookupExpr *ULE = dyn_cast(Callee)) { - assert(ULE->requiresADL()); Functions.append(ULE->decls_begin(), ULE->decls_end()); + // If the overload could not be resolved in the template definition + // (because we had a dependent argument), ADL is performed as part of + // template instantiation. + RequiresADL = ULE->requiresADL(); } else { // If we've resolved this to a particular non-member function, just call // that function. If we resolved it to a member function, @@ -12647,6 +12650,7 @@ NamedDecl *ND = cast(Callee)->getDecl(); if (!isa(ND)) Functions.addDecl(ND); + RequiresADL = false; } // Add any functions found via argument-dependent lookup. @@ -12657,7 +12661,8 @@ if (NumArgs == 1 || isPostIncDec) { UnaryOperatorKind Opc = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); - return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First); + return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First, + RequiresADL); } if (Op == OO_Subscript) { @@ -12681,8 +12686,8 @@ // Create the overloaded operator invocation for binary operators. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); - ExprResult Result - = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]); + ExprResult Result = SemaRef.CreateOverloadedBinOp( + OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL); if (Result.isInvalid()) return ExprError(); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTReader.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTReader.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTReader.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTReader.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -5425,10 +5425,12 @@ llvm_unreachable("Invalid PreprocessorDetailRecordTypes"); } -/// \brief \arg SLocMapI points at a chunk of a module that contains no -/// preprocessed entities or the entities it contains are not the ones we are -/// looking for. Find the next module that contains entities and return the ID +/// \brief Find the next module that contains entities and return the ID /// of the first entry. +/// +/// \param SLocMapI points at a chunk of a module that contains no +/// preprocessed entities or the entities it contains are not the ones we are +/// looking for. PreprocessedEntityID ASTReader::findNextPreprocessedEntity( GlobalSLocOffsetMapType::const_iterator SLocMapI) const { ++SLocMapI; @@ -5728,7 +5730,8 @@ // Preserve the property that the imaginary root file describes the // current state. - auto &T = Diag.DiagStatesByLoc.Files[FileID()].StateTransitions; + FileID NullFile; + auto &T = Diag.DiagStatesByLoc.Files[NullFile].StateTransitions; if (T.empty()) T.push_back({CurState, 0}); else diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTReaderDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTReaderDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTReaderDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTReaderDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1901,9 +1901,12 @@ if (auto *OperatorDelete = ReadDeclAs()) { auto *Canon = cast(D->getCanonicalDecl()); + auto *ThisArg = Record.readExpr(); // FIXME: Check consistency if we have an old and new operator delete. - if (!Canon->OperatorDelete) + if (!Canon->OperatorDelete) { Canon->OperatorDelete = OperatorDelete; + Canon->OperatorDeleteThisArg = ThisArg; + } } } @@ -4113,9 +4116,12 @@ // record. auto *Del = ReadDeclAs(); auto *First = cast(D->getCanonicalDecl()); + auto *ThisArg = Record.readExpr(); // FIXME: Check consistency if we have an old and new operator delete. - if (!First->OperatorDelete) + if (!First->OperatorDelete) { First->OperatorDelete = Del; + First->OperatorDeleteThisArg = ThisArg; + } break; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTWriter.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTWriter.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTWriter.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTWriter.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -5151,6 +5151,7 @@ case UPD_CXX_RESOLVED_DTOR_DELETE: Record.AddDeclRef(Update.getDecl()); + Record.AddStmt(cast(D)->getOperatorDeleteThisArg()); break; case UPD_CXX_RESOLVED_EXCEPTION_SPEC: @@ -6178,7 +6179,8 @@ } void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) { + const FunctionDecl *Delete, + Expr *ThisArg) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); assert(Delete && "Not given an operator delete"); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTWriterDecl.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTWriterDecl.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Serialization/ASTWriterDecl.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Serialization/ASTWriterDecl.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1309,6 +1309,8 @@ VisitCXXMethodDecl(D); Record.AddDeclRef(D->getOperatorDelete()); + if (D->getOperatorDelete()) + Record.AddStmt(D->getOperatorDeleteThisArg()); Code = serialization::DECL_CXX_DESTRUCTOR; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 2017-10-17 14:41:55.000000000 +0000 @@ -57,6 +57,7 @@ NSErrorChecker.cpp NoReturnFunctionChecker.cpp NonNullParamChecker.cpp + NonnullGlobalConstantsChecker.cpp NullabilityChecker.cpp NumberObjectConversionChecker.cpp ObjCAtSyncChecker.cpp diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -123,57 +123,6 @@ C.emitReport(std::move(R)); } -// Is E value greater or equal than Val? -static bool isGreaterEqual(CheckerContext &C, const Expr *E, - unsigned long long Val) { - ProgramStateRef State = C.getState(); - SVal EVal = C.getSVal(E); - if (EVal.isUnknownOrUndef()) - return false; - if (!EVal.getAs() && EVal.getAs()) { - ProgramStateManager &Mgr = C.getStateManager(); - EVal = - Mgr.getStoreManager().getBinding(State->getStore(), EVal.castAs()); - } - if (EVal.isUnknownOrUndef() || !EVal.getAs()) - return false; - - SValBuilder &Bldr = C.getSValBuilder(); - DefinedSVal V = Bldr.makeIntVal(Val, C.getASTContext().LongLongTy); - - // Is DefinedEVal greater or equal with V? - SVal GE = Bldr.evalBinOp(State, BO_GE, EVal, V, Bldr.getConditionType()); - if (GE.isUnknownOrUndef()) - return false; - ConstraintManager &CM = C.getConstraintManager(); - ProgramStateRef StGE, StLT; - std::tie(StGE, StLT) = CM.assumeDual(State, GE.castAs()); - return StGE && !StLT; -} - -// Is E value negative? -static bool isNegative(CheckerContext &C, const Expr *E) { - ProgramStateRef State = C.getState(); - SVal EVal = State->getSVal(E, C.getLocationContext()); - if (EVal.isUnknownOrUndef() || !EVal.getAs()) - return false; - DefinedSVal DefinedEVal = EVal.castAs(); - - SValBuilder &Bldr = C.getSValBuilder(); - DefinedSVal V = Bldr.makeIntVal(0, false); - - SVal LT = - Bldr.evalBinOp(State, BO_LT, DefinedEVal, V, Bldr.getConditionType()); - - // Is E value greater than MaxVal? - ConstraintManager &CM = C.getConstraintManager(); - ProgramStateRef StNegative, StPositive; - std::tie(StNegative, StPositive) = - CM.assumeDual(State, LT.castAs()); - - return StNegative && !StPositive; -} - bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast, QualType DestType, CheckerContext &C) const { @@ -195,18 +144,18 @@ return false; unsigned long long MaxVal = 1ULL << W; - return isGreaterEqual(C, Cast->getSubExpr(), MaxVal); + return C.isGreaterOrEqual(Cast->getSubExpr(), MaxVal); } bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast, - CheckerContext &C) const { + CheckerContext &C) const { QualType CastType = Cast->getType(); QualType SubType = Cast->IgnoreParenImpCasts()->getType(); if (!CastType->isUnsignedIntegerType() || !SubType->isSignedIntegerType()) return false; - return isNegative(C, Cast->getSubExpr()); + return C.isNegative(Cast->getSubExpr()); } void ento::registerConversionChecker(CheckerManager &mgr) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1050,31 +1050,22 @@ // If this is mempcpy, get the byte after the last byte copied and // bind the expr. if (IsMempcpy) { - loc::MemRegionVal destRegVal = destVal.castAs(); - - // Get the length to copy. - if (Optional lenValNonLoc = sizeVal.getAs()) { - // Get the byte after the last byte copied. - SValBuilder &SvalBuilder = C.getSValBuilder(); - ASTContext &Ctx = SvalBuilder.getContext(); - QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); - loc::MemRegionVal DestRegCharVal = SvalBuilder.evalCast(destRegVal, - CharPtrTy, Dest->getType()).castAs(); - SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, - DestRegCharVal, - *lenValNonLoc, - Dest->getType()); - - // The byte after the last byte copied is the return value. - state = state->BindExpr(CE, LCtx, lastElement); - } else { - // If we don't know how much we copied, we can at least - // conjure a return value for later. - SVal result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, + // Get the byte after the last byte copied. + SValBuilder &SvalBuilder = C.getSValBuilder(); + ASTContext &Ctx = SvalBuilder.getContext(); + QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); + SVal DestRegCharVal = + SvalBuilder.evalCast(destVal, CharPtrTy, Dest->getType()); + SVal lastElement = C.getSValBuilder().evalBinOp( + state, BO_Add, DestRegCharVal, sizeVal, Dest->getType()); + // If we don't know how much we copied, we can at least + // conjure a return value for later. + if (lastElement.isUnknown()) + lastElement = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()); - state = state->BindExpr(CE, LCtx, result); - } + // The byte after the last byte copied is the return value. + state = state->BindExpr(CE, LCtx, lastElement); } else { // All other copies return the destination buffer. // (Well, bcopy() has a void return type, but this won't hurt.) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -56,6 +56,8 @@ ArrayRef ExplicitRegions, ArrayRef Regions, const LocationContext *LCtx, const CallEvent *Call) const; + void printState(raw_ostream &Out, ProgramStateRef State, + const char *NL, const char *Sep) const override; private: class MovedBugVisitor : public BugReporterVisitorImpl { @@ -414,7 +416,14 @@ return; if (isStateResetMethod(MethodDecl)) { - State = State->remove(ThisRegion); + // A state reset method resets the whole object, not only sub-object + // of a parent class in which it is defined. + const MemRegion *WholeObjectRegion = ThisRegion; + while (const CXXBaseObjectRegion *BR = + dyn_cast(WholeObjectRegion)) + WholeObjectRegion = BR->getSuperRegion(); + + State = State->remove(WholeObjectRegion); C.addTransition(State); return; } @@ -476,6 +485,25 @@ return State; } +void MisusedMovedObjectChecker::printState(raw_ostream &Out, + ProgramStateRef State, + const char *NL, + const char *Sep) const { + + TrackedRegionMapTy RS = State->get(); + + if (!RS.isEmpty()) { + Out << Sep << "Moved-from objects :" << NL; + for (auto I: RS) { + I.first->dumpToStream(Out); + if (I.second.isMoved()) + Out << ": moved"; + else + Out << ": moved and reported"; + Out << NL; + } + } +} void ento::registerMisusedMovedObjectChecker(CheckerManager &mgr) { mgr.registerChecker(); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,140 @@ +//==- NonnullGlobalConstantsChecker.cpp ---------------------------*- C++ -*--// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This checker adds an assumption that constant globals of certain types* are +// non-null, as otherwise they generally do not convey any useful information. +// The assumption is useful, as many framework use e. g. global const strings, +// and the analyzer might not be able to infer the global value if the +// definition is in a separate translation unit. +// The following types (and their typedef aliases) are considered to be +// non-null: +// - `char* const` +// - `const CFStringRef` from CoreFoundation +// - `NSString* const` from Foundation +// - `CFBooleanRef` from Foundation +// +//===----------------------------------------------------------------------===// + +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" + +using namespace clang; +using namespace ento; + +namespace { + +class NonnullGlobalConstantsChecker : public Checker { + mutable IdentifierInfo *NSStringII = nullptr; + mutable IdentifierInfo *CFStringRefII = nullptr; + mutable IdentifierInfo *CFBooleanRefII = nullptr; + +public: + NonnullGlobalConstantsChecker() {} + + void checkLocation(SVal l, bool isLoad, const Stmt *S, + CheckerContext &C) const; + +private: + void initIdentifierInfo(ASTContext &Ctx) const; + + bool isGlobalConstString(SVal V) const; + + bool isNonnullType(QualType Ty) const; +}; + +} // namespace + +/// Lazily initialize cache for required identifier informations. +void NonnullGlobalConstantsChecker::initIdentifierInfo(ASTContext &Ctx) const { + if (NSStringII) + return; + + NSStringII = &Ctx.Idents.get("NSString"); + CFStringRefII = &Ctx.Idents.get("CFStringRef"); + CFBooleanRefII = &Ctx.Idents.get("CFBooleanRef"); +} + +/// Add an assumption that const string-like globals are non-null. +void NonnullGlobalConstantsChecker::checkLocation(SVal location, bool isLoad, + const Stmt *S, + CheckerContext &C) const { + initIdentifierInfo(C.getASTContext()); + if (!isLoad || !location.isValid()) + return; + + ProgramStateRef State = C.getState(); + SVal V = State->getSVal(location.castAs()); + + if (isGlobalConstString(location)) { + Optional Constr = V.getAs(); + + if (Constr) { + + // Assume that the variable is non-null. + ProgramStateRef OutputState = State->assume(*Constr, true); + C.addTransition(OutputState); + } + } +} + +/// \param V loaded lvalue. +/// \return whether {@code val} is a string-like const global. +bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const { + Optional RegionVal = V.getAs(); + if (!RegionVal) + return false; + auto *Region = dyn_cast(RegionVal->getAsRegion()); + if (!Region) + return false; + const VarDecl *Decl = Region->getDecl(); + + if (!Decl->hasGlobalStorage()) + return false; + + QualType Ty = Decl->getType(); + bool HasConst = Ty.isConstQualified(); + if (isNonnullType(Ty) && HasConst) + return true; + + // Look through the typedefs. + while (auto *T = dyn_cast(Ty)) { + Ty = T->getDecl()->getUnderlyingType(); + + // It is sufficient for any intermediate typedef + // to be classified const. + HasConst = HasConst || Ty.isConstQualified(); + if (isNonnullType(Ty) && HasConst) + return true; + } + return false; +} + +/// \return whether {@code type} is extremely unlikely to be null +bool NonnullGlobalConstantsChecker::isNonnullType(QualType Ty) const { + + if (Ty->isPointerType() && Ty->getPointeeType()->isCharType()) + return true; + + if (auto *T = dyn_cast(Ty)) { + return T->getInterfaceDecl() && + T->getInterfaceDecl()->getIdentifier() == NSStringII; + } else if (auto *T = dyn_cast(Ty)) { + IdentifierInfo* II = T->getDecl()->getIdentifier(); + return II == CFStringRefII || II == CFBooleanRefII; + } + return false; +} + +void ento::registerNonnullGlobalConstantsChecker(CheckerManager &Mgr) { + Mgr.registerChecker(); +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -81,6 +81,8 @@ public: void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; + void printState(raw_ostream &Out, ProgramStateRef State, + const char *NL, const char *Sep) const override; void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock, bool isTryLock, enum LockingSemantics semantics) const; @@ -184,6 +186,39 @@ return state; } +void PthreadLockChecker::printState(raw_ostream &Out, ProgramStateRef State, + const char *NL, const char *Sep) const { + LockMapTy LM = State->get(); + if (!LM.isEmpty()) { + Out << Sep << "Mutex states:" << NL; + for (auto I : LM) { + I.first->dumpToStream(Out); + if (I.second.isLocked()) + Out << ": locked"; + else if (I.second.isUnlocked()) + Out << ": unlocked"; + else if (I.second.isDestroyed()) + Out << ": destroyed"; + else if (I.second.isUntouchedAndPossiblyDestroyed()) + Out << ": not tracked, possibly destroyed"; + else if (I.second.isUnlockedAndPossiblyDestroyed()) + Out << ": unlocked, possibly destroyed"; + Out << NL; + } + } + + LockSetTy LS = State->get(); + if (!LS.isEmpty()) { + Out << Sep << "Mutex lock order:" << NL; + for (auto I: LS) { + I->dumpToStream(Out); + Out << NL; + } + } + + // TODO: Dump destroyed mutex symbols? +} + void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock, bool isTryLock, enum LockingSemantics semantics) const { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1062,6 +1062,7 @@ // Inspect the result type. QualType RetTy = FT->getReturnType(); + std::string RetTyName = RetTy.getAsString(); // FIXME: This should all be refactored into a chain of "summary lookup" // filters. @@ -1081,12 +1082,14 @@ AllowAnnotations = false; } else if (FName == "CFPlugInInstanceCreate") { S = getPersistentSummary(RetEffect::MakeNoRet()); - } else if (FName == "IOBSDNameMatching" || + } else if (FName == "IORegistryEntrySearchCFProperty" + || (RetTyName == "CFMutableDictionaryRef" && ( + FName == "IOBSDNameMatching" || FName == "IOServiceMatching" || FName == "IOServiceNameMatching" || - FName == "IORegistryEntrySearchCFProperty" || FName == "IORegistryEntryIDMatching" || - FName == "IOOpenFirmwarePathMatching") { + FName == "IOOpenFirmwarePathMatching" + ))) { // Part of . (IOKit) // This should be addressed using a API table. S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), @@ -1167,6 +1170,11 @@ if (cocoa::isRefType(RetTy, "CF", FName)) { if (isRetain(FD, FName)) { S = getUnarySummary(FT, cfretain); + // CFRetain isn't supposed to be annotated. However, this may as well + // be a user-made "safe" CFRetain function that is incorrectly + // annotated as cf_returns_retained due to lack of better options. + // We want to ignore such annotation. + AllowAnnotations = false; } else if (isAutorelease(FD, FName)) { S = getUnarySummary(FT, cfautorelease); // The headers use cf_consumed, but we can fully model CFAutorelease diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -59,6 +59,11 @@ return StOutBound && !StInBound; } +static bool isShiftOverflow(const BinaryOperator *B, CheckerContext &C) { + return C.isGreaterOrEqual( + B->getRHS(), C.getASTContext().getIntWidth(B->getLHS()->getType())); +} + void UndefResultChecker::checkPostStmt(const BinaryOperator *B, CheckerContext &C) const { ProgramStateRef state = C.getState(); @@ -97,18 +102,46 @@ } if (Ex) { - OS << "The " << (isLeft ? "left" : "right") - << " operand of '" + OS << "The " << (isLeft ? "left" : "right") << " operand of '" << BinaryOperator::getOpcodeStr(B->getOpcode()) << "' is a garbage value"; if (isArrayIndexOutOfBounds(C, Ex)) OS << " due to array index out of bounds"; - } - else { + } else { // Neither operand was undefined, but the result is undefined. - OS << "The result of the '" - << BinaryOperator::getOpcodeStr(B->getOpcode()) - << "' expression is undefined"; + if ((B->getOpcode() == BinaryOperatorKind::BO_Shl || + B->getOpcode() == BinaryOperatorKind::BO_Shr) && + C.isNegative(B->getRHS())) { + OS << "The result of the " + << ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left" + : "right") + << " shift is undefined because the right operand is negative"; + } else if ((B->getOpcode() == BinaryOperatorKind::BO_Shl || + B->getOpcode() == BinaryOperatorKind::BO_Shr) && + isShiftOverflow(B, C)) { + + OS << "The result of the " + << ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left" + : "right") + << " shift is undefined due to shifting by "; + + SValBuilder &SB = C.getSValBuilder(); + const llvm::APSInt *I = + SB.getKnownValue(C.getState(), C.getSVal(B->getRHS())); + if (!I) + OS << "a value that is"; + else if (I->isUnsigned()) + OS << '\'' << I->getZExtValue() << "\', which is"; + else + OS << '\'' << I->getSExtValue() << "\', which is"; + + OS << " greater or equal to the width of type '" + << B->getLHS()->getType().getAsString() << "'."; + } else { + OS << "The result of the '" + << BinaryOperator::getOpcodeStr(B->getOpcode()) + << "' expression is undefined"; + } } auto report = llvm::make_unique(*BT, OS.str(), N); if (Ex) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -99,3 +99,35 @@ return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts()); } +/// Evaluate comparison and return true if it's known that condition is true +static bool evalComparison(SVal LHSVal, BinaryOperatorKind ComparisonOp, + SVal RHSVal, ProgramStateRef State) { + if (LHSVal.isUnknownOrUndef()) + return false; + ProgramStateManager &Mgr = State->getStateManager(); + if (!LHSVal.getAs()) { + LHSVal = Mgr.getStoreManager().getBinding(State->getStore(), + LHSVal.castAs()); + if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs()) + return false; + } + + SValBuilder &Bldr = Mgr.getSValBuilder(); + SVal Eval = Bldr.evalBinOp(State, ComparisonOp, LHSVal, RHSVal, + Bldr.getConditionType()); + if (Eval.isUnknownOrUndef()) + return false; + ProgramStateRef StTrue, StFalse; + std::tie(StTrue, StFalse) = State->assume(Eval.castAs()); + return StTrue && !StFalse; +} + +bool CheckerContext::isGreaterOrEqual(const Expr *E, unsigned long long Val) { + DefinedSVal V = getSValBuilder().makeIntVal(Val, getASTContext().LongLongTy); + return evalComparison(getSVal(E), BO_GE, V, getState()); +} + +bool CheckerContext::isNegative(const Expr *E) { + DefinedSVal V = getSValBuilder().makeIntVal(0, false); + return evalComparison(getSVal(E), BO_LT, V, getState()); +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -827,6 +827,21 @@ } } +namespace { +class CollectReachableSymbolsCallback final : public SymbolVisitor { + InvalidatedSymbols Symbols; + +public: + explicit CollectReachableSymbolsCallback(ProgramStateRef State) {} + const InvalidatedSymbols &getSymbols() const { return Symbols; } + + bool VisitSymbol(SymbolRef Sym) override { + Symbols.insert(Sym); + return true; + } +}; +} // end anonymous namespace + void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &DstTop) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), @@ -1103,8 +1118,29 @@ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, resultType, currBldrCtx->blockCount()); - ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result); - Bldr2.generateNode(S, N, state); + ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result); + + // Escape pointers passed into the list, unless it's an ObjC boxed + // expression which is not a boxable C structure. + if (!(isa(Ex) && + !cast(Ex)->getSubExpr() + ->getType()->isRecordType())) + for (auto Child : Ex->children()) { + assert(Child); + + SVal Val = State->getSVal(Child, LCtx); + + CollectReachableSymbolsCallback Scanner = + State->scanReachableSymbols( + Val); + const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols(); + + State = getCheckerManager().runCheckersForPointerEscape( + State, EscapedSymbols, + /*CallEvent*/ nullptr, PSK_EscapeOther, nullptr); + } + + Bldr2.generateNode(S, N, State); } getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this); @@ -2237,21 +2273,6 @@ getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this); } -namespace { -class CollectReachableSymbolsCallback final : public SymbolVisitor { - InvalidatedSymbols Symbols; - -public: - CollectReachableSymbolsCallback(ProgramStateRef State) {} - const InvalidatedSymbols &getSymbols() const { return Symbols; } - - bool VisitSymbol(SymbolRef Sym) override { - Symbols.insert(Sym); - return true; - } -}; -} // end anonymous namespace - // A value escapes in three possible cases: // (1) We are binding to something that is not a memory region. // (2) We are binding to a MemrRegion that does not have stack storage. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/RegionStore.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/RegionStore.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/RegionStore.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/RegionStore.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1393,16 +1393,19 @@ return UnknownVal(); } - if (isa(MR) || - isa(MR) || - isa(MR)) { + if (!isa(MR)) { if (T.isNull()) { if (const TypedRegion *TR = dyn_cast(MR)) - T = TR->getLocationType(); - else { - const SymbolicRegion *SR = cast(MR); - T = SR->getSymbol()->getType(); - } + T = TR->getLocationType()->getPointeeType(); + else if (const SymbolicRegion *SR = dyn_cast(MR)) + T = SR->getSymbol()->getType()->getPointeeType(); + else if (isa(MR)) + T = Ctx.VoidTy; + } + assert(!T.isNull() && "Unable to auto-detect binding type!"); + if (T->isVoidType()) { + // When trying to dereference a void pointer, read the first byte. + T = Ctx.CharTy; } MR = GetElementZeroRegion(cast(MR), T); } @@ -2085,15 +2088,12 @@ if (const ConstantArrayType* CAT = dyn_cast(AT)) Size = CAT->getSize().getZExtValue(); - // Check if the init expr is a string literal. + // Check if the init expr is a literal. If so, bind the rvalue instead. + // FIXME: It's not responsibility of the Store to transform this lvalue + // to rvalue. ExprEngine or maybe even CFG should do this before binding. if (Optional MRV = Init.getAs()) { - const StringRegion *S = cast(MRV->getRegion()); - - // Treat the string as a lazy compound value. - StoreRef store(B.asStore(), *this); - nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S) - .castAs(); - return bindAggregate(B, R, LCV); + SVal V = getBinding(B.asStore(), *MRV, R->getValueType()); + return bindAggregate(B, R, V); } // Handle lazy compound values. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -922,6 +922,10 @@ if (rhs.isZeroConstant()) return lhs; + // Perserve the null pointer so that it can be found by the DerefChecker. + if (lhs.isZeroConstant()) + return lhs; + // We are dealing with pointer arithmetic. // Handle pointer arithmetic on constant values. @@ -937,6 +941,8 @@ // Offset the increment by the pointer size. llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true); + QualType pointeeType = resultTy->getPointeeType(); + Multiplicand = getContext().getTypeSizeInChars(pointeeType).getQuantity(); rightI *= Multiplicand; // Compute the adjusted pointer. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/SVals.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/SVals.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/StaticAnalyzer/Core/SVals.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/StaticAnalyzer/Core/SVals.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -113,12 +113,12 @@ /// Casts are ignored during lookup. /// \param IncludeBaseRegions The boolean that controls whether the search /// should continue to the base regions if the region is not symbolic. -SymbolRef SVal::getAsSymbol(bool IncludeBaseRegion) const { +SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const { // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? if (Optional X = getAs()) return X->getSymbol(); - return getAsLocSymbol(IncludeBaseRegion); + return getAsLocSymbol(IncludeBaseRegions); } /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -23,6 +23,9 @@ #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Refactoring/RefactoringAction.h" +#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" +#include "clang/Tooling/Refactoring/RefactoringOptions.h" +#include "clang/Tooling/Refactoring/Rename/SymbolName.h" #include "clang/Tooling/Refactoring/Rename/USRFinder.h" #include "clang/Tooling/Refactoring/Rename/USRFindingAction.h" #include "clang/Tooling/Refactoring/Rename/USRLocFinder.h" @@ -47,11 +50,9 @@ return Selection.takeError(); const NamedDecl *ND = getNamedDeclAt(Context.getASTContext(), Selection->getBegin()); - if (!ND) { - // FIXME: Use a diagnostic. - return llvm::make_error("no symbol selected", - llvm::inconvertibleErrorCode()); - } + if (!ND) + return Context.createDiagnosticError( + Selection->getBegin(), diag::err_refactor_selection_no_symbol); return getCanonicalSymbolDeclaration(ND); } }; @@ -75,7 +76,8 @@ class RenameOccurrences final : public SourceChangeRefactoringRule { public: - RenameOccurrences(const NamedDecl *ND) : Finder(ND) {} + RenameOccurrences(const NamedDecl *ND, std::string NewName) + : Finder(ND), NewName(NewName) {} Expected createSourceReplacements(RefactoringRuleContext &Context) { @@ -83,15 +85,15 @@ Finder.findSymbolOccurrences(Context); if (!Occurrences) return Occurrences.takeError(); - // FIXME: This is a temporary workaround that's needed until the refactoring - // options are implemented. - StringRef NewName = "Bar"; + // FIXME: Verify that the new name is valid. + SymbolName Name(NewName); return createRenameReplacements( - *Occurrences, Context.getASTContext().getSourceManager(), NewName); + *Occurrences, Context.getASTContext().getSourceManager(), Name); } private: OccurrenceFinder Finder; + std::string NewName; }; class LocalRename final : public RefactoringAction { @@ -107,7 +109,7 @@ RefactoringActionRules createActionRules() const override { RefactoringActionRules Rules; Rules.push_back(createRefactoringActionRule( - SymbolSelectionRequirement())); + SymbolSelectionRequirement(), OptionRequirement())); return Rules; } }; @@ -120,19 +122,18 @@ Expected> createRenameReplacements(const SymbolOccurrences &Occurrences, - const SourceManager &SM, - ArrayRef NewNameStrings) { + const SourceManager &SM, const SymbolName &NewName) { // FIXME: A true local rename can use just one AtomicChange. std::vector Changes; for (const auto &Occurrence : Occurrences) { ArrayRef Ranges = Occurrence.getNameRanges(); - assert(NewNameStrings.size() == Ranges.size() && + assert(NewName.getNamePieces().size() == Ranges.size() && "Mismatching number of ranges and name pieces"); AtomicChange Change(SM, Ranges[0].getBegin()); for (const auto &Range : llvm::enumerate(Ranges)) { auto Error = Change.replace(SM, CharSourceRange::getCharRange(Range.value()), - NewNameStrings[Range.index()]); + NewName.getNamePieces()[Range.index()]); if (Error) return std::move(Error); } @@ -196,7 +197,7 @@ } // FIXME: Support multi-piece names. // FIXME: better error handling (propagate error out). - StringRef NewNameRef = NewName; + SymbolName NewNameRef(NewName); Expected> Change = createRenameReplacements(Occurrences, SourceMgr, NewNameRef); if (!Change) { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -160,13 +160,14 @@ const Decl *Context; // The nested name being replaced (can be nullptr). const NestedNameSpecifier *Specifier; + // Determine whether the prefix qualifiers of the NewName should be ignored. + // Normally, we set it to true for the symbol declaration and definition to + // avoid adding prefix qualifiers. + // For example, if it is true and NewName is "a::b::foo", then the symbol + // occurrence which the RenameInfo points to will be renamed to "foo". + bool IgnorePrefixQualifers; }; - // 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(Decl)) @@ -180,8 +181,12 @@ return true; if (isInUSRSet(Decl)) { - RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr, - nullptr, nullptr}; + RenameInfo Info = {Decl->getLocation(), + Decl->getLocation(), + /*FromDecl=*/nullptr, + /*Context=*/nullptr, + /*Specifier=*/nullptr, + /*IgnorePrefixQualifers=*/true}; RenameInfos.push_back(Info); } return true; @@ -189,10 +194,52 @@ bool VisitDeclRefExpr(const DeclRefExpr *Expr) { const NamedDecl *Decl = Expr->getFoundDecl(); + // Get the underlying declaration of the shadow declaration introduced by a + // using declaration. + if (auto *UsingShadow = llvm::dyn_cast(Decl)) { + Decl = UsingShadow->getTargetDecl(); + } + + auto BeginLoc = Expr->getLocStart(); + auto EndLoc = Expr->getLocEnd(); + // In case of renaming an enum declaration, we have to explicitly handle + // unscoped enum constants referenced in expressions (e.g. + // "auto r = ns1::ns2::Green" where Green is an enum constant of an unscoped + // enum decl "ns1::ns2::Color") as these enum constants cannot be caught by + // TypeLoc. + if (const auto *T = llvm::dyn_cast(Decl)) { + // FIXME: Handle the enum constant without prefix qualifiers (`a = Green`) + // when renaming an unscoped enum declaration with a new namespace. + if (!Expr->hasQualifier()) + return true; + + if (const auto *ED = + llvm::dyn_cast_or_null(getClosestAncestorDecl(*T))) { + if (ED->isScoped()) + return true; + Decl = ED; + } + // The current fix would qualify "ns1::ns2::Green" as + // "ns1::ns2::Color::Green". + // + // Get the EndLoc of the replacement by moving 1 character backward ( + // to exclude the last '::'). + // + // ns1::ns2::Green; + // ^ ^^ + // BeginLoc |EndLoc of the qualifier + // new EndLoc + EndLoc = Expr->getQualifierLoc().getEndLoc().getLocWithOffset(-1); + assert(EndLoc.isValid() && + "The enum constant should have prefix qualifers."); + } if (isInUSRSet(Decl)) { - RenameInfo Info = {Expr->getSourceRange().getBegin(), - Expr->getSourceRange().getEnd(), Decl, - getClosestAncestorDecl(*Expr), Expr->getQualifier()}; + RenameInfo Info = {BeginLoc, + EndLoc, + Decl, + getClosestAncestorDecl(*Expr), + Expr->getQualifier(), + /*IgnorePrefixQualifers=*/false}; RenameInfos.push_back(Info); } @@ -220,8 +267,10 @@ if (isInUSRSet(TargetDecl)) { RenameInfo Info = {NestedLoc.getBeginLoc(), EndLocationForType(NestedLoc.getTypeLoc()), - TargetDecl, getClosestAncestorDecl(NestedLoc), - NestedLoc.getNestedNameSpecifier()->getPrefix()}; + TargetDecl, + getClosestAncestorDecl(NestedLoc), + NestedLoc.getNestedNameSpecifier()->getPrefix(), + /*IgnorePrefixQualifers=*/false}; RenameInfos.push_back(Info); } } @@ -265,9 +314,12 @@ if (!ParentTypeLoc.isNull() && isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc))) return true; - RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc), - TargetDecl, getClosestAncestorDecl(Loc), - GetNestedNameForType(Loc)}; + RenameInfo Info = {StartLocationForType(Loc), + EndLocationForType(Loc), + TargetDecl, + getClosestAncestorDecl(Loc), + GetNestedNameForType(Loc), + /*IgnorePrefixQualifers=*/false}; RenameInfos.push_back(Info); return true; } @@ -293,11 +345,13 @@ llvm::isa(ParentTypeLoc.getType())) TargetLoc = ParentTypeLoc; RenameInfo Info = { - StartLocationForType(TargetLoc), EndLocationForType(TargetLoc), + StartLocationForType(TargetLoc), + EndLocationForType(TargetLoc), TemplateSpecType->getTemplateName().getAsTemplateDecl(), getClosestAncestorDecl( ast_type_traits::DynTypedNode::create(TargetLoc)), - GetNestedNameForType(TargetLoc)}; + GetNestedNameForType(TargetLoc), + /*IgnorePrefixQualifers=*/false}; RenameInfos.push_back(Info); } } @@ -343,10 +397,13 @@ // 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. + // FIXME: support more types, e.g. type alias. const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) { if (const auto *RD = Loc.getType()->getAsCXXRecordDecl()) return RD; + if (const auto *ED = + llvm::dyn_cast_or_null(Loc.getType()->getAsTagDecl())) + return ED; return nullptr; } @@ -423,18 +480,43 @@ for (const auto &RenameInfo : Finder.getRenameInfos()) { std::string ReplacedName = NewName.str(); - if (RenameInfo.FromDecl && RenameInfo.Context) { - if (!llvm::isa( - RenameInfo.Context->getDeclContext())) { - ReplacedName = tooling::replaceNestedName( - RenameInfo.Specifier, RenameInfo.Context->getDeclContext(), - RenameInfo.FromDecl, - NewName.startswith("::") ? NewName.str() : ("::" + NewName).str()); + if (RenameInfo.IgnorePrefixQualifers) { + // Get the name without prefix qualifiers from NewName. + size_t LastColonPos = NewName.find_last_of(':'); + if (LastColonPos != std::string::npos) + ReplacedName = NewName.substr(LastColonPos + 1); + } else { + if (RenameInfo.FromDecl && RenameInfo.Context) { + if (!llvm::isa( + RenameInfo.Context->getDeclContext())) { + ReplacedName = tooling::replaceNestedName( + RenameInfo.Specifier, RenameInfo.Context->getDeclContext(), + RenameInfo.FromDecl, + NewName.startswith("::") ? NewName.str() + : ("::" + NewName).str()); + } else { + // This fixes the case where type `T` is a parameter inside a function + // type (e.g. `std::function`) and the DeclContext of `T` + // becomes the translation unit. As a workaround, we simply use + // fully-qualified name here for all references whose `DeclContext` is + // the translation unit and ignore the possible existence of + // using-decls (in the global scope) that can shorten the replaced + // name. + llvm::StringRef ActualName = Lexer::getSourceText( + CharSourceRange::getTokenRange( + SourceRange(RenameInfo.Begin, RenameInfo.End)), + SM, TranslationUnitDecl->getASTContext().getLangOpts()); + // Add the leading "::" back if the name written in the code contains + // it. + if (ActualName.startswith("::") && !NewName.startswith("::")) { + ReplacedName = "::" + NewName.str(); + } + } } + // If the NewName contains leading "::", add it back. + if (NewName.startswith("::") && NewName.substr(2) == ReplacedName) + ReplacedName = 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); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/runtime/CMakeLists.txt llvm-toolchain-snapshot-6.0~svn316003/clang/runtime/CMakeLists.txt --- llvm-toolchain-snapshot-6.0~svn314833/clang/runtime/CMakeLists.txt 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/runtime/CMakeLists.txt 2017-10-17 14:41:55.000000000 +0000 @@ -109,7 +109,7 @@ USES_TERMINAL) # Add top-level targets that build specific compiler-rt runtimes. - set(COMPILER_RT_RUNTIMES asan builtins dfsan lsan msan profile tsan ubsan ubsan-minimal) + set(COMPILER_RT_RUNTIMES fuzzer asan builtins dfsan lsan msan profile tsan ubsan ubsan-minimal) foreach(runtime ${COMPILER_RT_RUNTIMES}) get_ext_project_build_command(build_runtime_cmd ${runtime}) add_custom_target(${runtime} @@ -125,7 +125,7 @@ FileCheck count not llvm-nm llvm-objdump llvm-symbolizer) # Add top-level targets for various compiler-rt test suites. - set(COMPILER_RT_TEST_SUITES check-asan check-asan-dynamic check-dfsan + set(COMPILER_RT_TEST_SUITES check-fuzzer check-asan check-asan-dynamic check-dfsan check-lsan check-msan check-sanitizer check-tsan check-ubsan check-ubsan-minimal check-profile check-cfi check-cfi-and-supported check-safestack) foreach(test_suite ${COMPILER_RT_TEST_SUITES}) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/bitwise-ops.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/bitwise-ops.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/bitwise-ops.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/bitwise-ops.c 2017-10-17 14:41:55.000000000 +0000 @@ -22,11 +22,25 @@ case 1: return 0ULL << 63; // no-warning case 2: - return 0ULL << 64; // expected-warning{{The result of the '<<' expression is undefined}} + return 0ULL << 64; // expected-warning{{The result of the left shift is undefined due to shifting by '64', which is greater or equal to the width of type 'unsigned long long'}} case 3: - return 0ULL << 65; // expected-warning{{The result of the '<<' expression is undefined}} + return 0ULL << 65; // expected-warning{{The result of the left shift is undefined due to shifting by '65', which is greater or equal to the width of type 'unsigned long long'}} default: return 0; } -} \ No newline at end of file +} + +int testOverflowShift(int a) { + if (a == 323) { + return 1 << a; // expected-warning{{The result of the left shift is undefined due to shifting by '323', which is greater or equal to the width of type 'int'}} + } + return 0; +} + +int testNegativeShift(int a) { + if (a == -5) { + return 1 << a; // expected-warning{{The result of the left shift is undefined because the right operand is negative}} + } + return 0; +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/bstring.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/bstring.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/bstring.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/bstring.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,8 +1,35 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s #include "Inputs/system-header-simulator-cxx.h" #include "Inputs/system-header-simulator-for-malloc.h" +// This provides us with four possible mempcpy() definitions. +// See also comments in bstring.c. + +#ifdef USE_BUILTINS +#define BUILTIN(f) __builtin_##f +#else /* USE_BUILTINS */ +#define BUILTIN(f) f +#endif /* USE_BUILTINS */ + +#ifdef VARIANT + +#define __mempcpy_chk BUILTIN(__mempcpy_chk) +void *__mempcpy_chk(void *__restrict__ s1, const void *__restrict__ s2, + size_t n, size_t destlen); + +#define mempcpy(a,b,c) __mempcpy_chk(a,b,c,(size_t)-1) + +#else /* VARIANT */ + +#define mempcpy BUILTIN(mempcpy) +void *mempcpy(void *__restrict__ s1, const void *__restrict__ s2, size_t n); + +#endif /* VARIANT */ + void clang_analyzer_eval(int); int *testStdCopyInvalidatesBuffer(std::vector v) { @@ -36,3 +63,17 @@ return buf; } + +namespace pr34460 { +short a; +class b { + int c; + long g; + void d() { + int e = c; + f += e; + mempcpy(f, &a, g); + } + unsigned *f; +}; +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/call_once.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/call_once.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/call_once.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/call_once.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,15 +1,24 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -w -verify %s +// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s void clang_analyzer_eval(bool); // Faking std::std::call_once implementation. namespace std { + +#ifndef EMULATE_LIBSTDCPP typedef struct once_flag_s { unsigned long __state_ = 0; } once_flag; +#else +typedef struct once_flag_s { + int _M_once = 0; +} once_flag; +#endif template void call_once(once_flag &o, Callable func, Args... args) {}; + } // namespace std // Check with Lambdas. @@ -231,3 +240,12 @@ int x = call_once(); clang_analyzer_eval(x == 5); // expected-warning{{TRUE}} } + +namespace std { +template +void call_once(d, e); +} +void g(); +void test_no_segfault_on_different_impl() { + std::call_once(g, false); // no-warning +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/casts.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/casts.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/casts.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/casts.c 2017-10-17 14:41:55.000000000 +0000 @@ -123,3 +123,29 @@ int x = (int) p; clang_analyzer_eval(++x < 10); // no-crash // expected-warning{{UNKNOWN}} } + +void multiDimensionalArrayPointerCasts() { + static int x[10][10]; + int *y1 = &(x[3][5]); + char *z = ((char *) y1) + 2; + int *y2 = (int *)(z - 2); + int *y3 = ((int *)x) + 35; // This is offset for [3][5]. + + clang_analyzer_eval(y1 == y2); // expected-warning{{TRUE}} + + // FIXME: should be FALSE (i.e. equal pointers). + clang_analyzer_eval(y1 - y2); // expected-warning{{UNKNOWN}} + // FIXME: should be TRUE (i.e. same symbol). + clang_analyzer_eval(*y1 == *y2); // expected-warning{{UNKNOWN}} + + clang_analyzer_eval(*((char *)y1) == *((char *) y2)); // expected-warning{{TRUE}} + + clang_analyzer_eval(y1 == y3); // expected-warning{{TRUE}} + + // FIXME: should be FALSE (i.e. equal pointers). + clang_analyzer_eval(y1 - y3); // expected-warning{{UNKNOWN}} + // FIXME: should be TRUE (i.e. same symbol). + clang_analyzer_eval(*y1 == *y3); // expected-warning{{UNKNOWN}} + + clang_analyzer_eval(*((char *)y1) == *((char *) y3)); // expected-warning{{TRUE}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/compound-literals.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/compound-literals.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/compound-literals.c 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/compound-literals.c 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple=i386-apple-darwin10 -analyze -analyzer-checker=debug.ExprInspection -verify %s +void clang_analyzer_eval(int); + +// pr28449: Used to crash. +void foo(void) { + static const unsigned short array[] = (const unsigned short[]){0x0F00}; + // FIXME: Should be true. + clang_analyzer_eval(array[0] == 0x0F00); // expected-warning{{UNKNOWN}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/conversion.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/conversion.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/conversion.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/conversion.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-conversion -analyzer-checker=core,alpha.core.Conversion -verify %s +// RUN: %clang_analyze_cc1 -Wno-conversion -Wno-tautological-constant-compare -analyzer-checker=core,alpha.core.Conversion -verify %s unsigned char U8; signed char S8; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/ctor.mm llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/ctor.mm --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/ctor.mm 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/ctor.mm 2017-10-17 14:41:55.000000000 +0000 @@ -199,7 +199,7 @@ Inner p; }; - void testPOD() { + void testPOD(const POD &pp) { POD p; p.x = 1; POD p2 = p; // no-warning @@ -210,6 +210,15 @@ // Use rvalues as well. clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}} + // Copy from symbolic references correctly. + POD p4 = pp; + // Make sure that p4.x contains a symbol after copy. + if (p4.x > 0) + clang_analyzer_eval(p4.x > 0); // expected-warning{{TRUE}} + // FIXME: Element region gets in the way, so these aren't the same symbols + // as they should be. + clang_analyzer_eval(pp.x == p4.x); // expected-warning{{UNKNOWN}} + PODWrapper w; w.p.y = 1; PODWrapper w2 = w; // no-warning diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/exercise-ps.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/exercise-ps.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/exercise-ps.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/exercise-ps.c 2017-10-17 14:41:55.000000000 +0000 @@ -21,3 +21,11 @@ memcpy((&x[1]), (buf), 1); // expected-warning{{implicitly declaring library function 'memcpy' with type 'void *(void *, const void *}} \ // expected-note{{include the header or explicitly provide a declaration for 'memcpy'}} } + +// AllocaRegion is untyped. Void pointer isn't of much help either. Before +// realizing that the value is undefined, we need to somehow figure out +// what type of value do we expect. +void f3(void *dest) { + void *src = __builtin_alloca(5); + memcpy(dest, src, 1); // expected-warning{{2nd function call argument is a pointer to uninitialized value}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/gtest.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/gtest.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/gtest.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/gtest.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -151,3 +151,17 @@ ASSERT_TRUE(false); clang_analyzer_warnIfReached(); // no-warning } + +void testAssertSymbolicPtr(const bool *b) { + ASSERT_TRUE(*b); // no-crash + + // FIXME: Our solver doesn't handle this well yet. + clang_analyzer_eval(*b); // expected-warning{{UNKNOWN}} +} + +void testAssertSymbolicRef(const bool &b) { + ASSERT_TRUE(b); // no-crash + + // FIXME: Our solver doesn't handle this well yet. + clang_analyzer_eval(b); // expected-warning{{UNKNOWN}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/initializer.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/initializer.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/initializer.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/initializer.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,7 +1,9 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s void clang_analyzer_eval(bool); +#include "Inputs/system-header-simulator-cxx.h" + class A { int x; public: @@ -204,3 +206,17 @@ const char(&f)[2]; }; } + +namespace CXX_initializer_lists { +struct C { + C(std::initializer_list list); +}; +void foo() { + C empty{}; // no-crash + + // Do not warn that 'x' leaks. It might have been deleted by + // the destructor of 'c'. + int *x = new int; + C c{x}; // no-warning +} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/MisusedMovedObject.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/MisusedMovedObject.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/MisusedMovedObject.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/MisusedMovedObject.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -617,3 +617,11 @@ a.b.foo(); // no-warning } } + +class C: public A {}; +void resetSuperClass() { + C c; + C c1 = std::move(c); + c.clear(); + C c2 = c; // no-warning +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/nonnull-global-constants.mm llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/nonnull-global-constants.mm --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/nonnull-global-constants.mm 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/nonnull-global-constants.mm 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,103 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +// Nullability of const string-like globals, testing +// NonnullGlobalConstantsChecker. + +void clang_analyzer_eval(bool); + +@class NSString; +typedef const struct __CFString *CFStringRef; +typedef const struct __CFBoolean * CFBooleanRef; + +// Global NSString* is non-null. +extern NSString *const StringConstGlobal; +void stringConstGlobal() { + clang_analyzer_eval(StringConstGlobal); // expected-warning{{TRUE}} +} + +// The logic does not apply to local variables though. +extern NSString *stringGetter(); +void stringConstLocal() { + NSString *const local = stringGetter(); + clang_analyzer_eval(local); // expected-warning{{UNKNOWN}} +} + +// Global const CFStringRef's are also assumed to be non-null. +extern const CFStringRef CFStringConstGlobal; +void cfStringCheckGlobal() { + clang_analyzer_eval(CFStringConstGlobal); // expected-warning{{TRUE}} +} + +// But only "const" ones. +extern CFStringRef CFStringNonConstGlobal; +void cfStringCheckMutableGlobal() { + clang_analyzer_eval(CFStringNonConstGlobal); // expected-warning{{UNKNOWN}} +} + +// char* const is also assumed to be non-null. +extern const char *const ConstCharStarConst; +void constCharStarCheckGlobal() { + clang_analyzer_eval(ConstCharStarConst); // expected-warning{{TRUE}} +} + +// Pointer value can be mutable. +extern char *const CharStarConst; +void charStarCheckGlobal() { + clang_analyzer_eval(CharStarConst); // expected-warning{{TRUE}} +} + +// But the pointer itself should be immutable. +extern char *CharStar; +void charStartCheckMutableGlobal() { + clang_analyzer_eval(CharStar); // expected-warning{{UNKNOWN}} +} + +// Type definitions should also work across typedefs, for pointers: +typedef char *const str; +extern str globalStr; +void charStarCheckTypedef() { + clang_analyzer_eval(globalStr); // expected-warning{{TRUE}} +} + +// And for types. +typedef NSString *const NStr; +extern NStr globalNSString; +void NSStringCheckTypedef() { + clang_analyzer_eval(globalNSString); // expected-warning{{TRUE}} +} + +// Note that constness could be either inside +// the var declaration, or in a typedef. +typedef NSString *NStr2; +extern const NStr2 globalNSString2; +void NSStringCheckConstTypedef() { + clang_analyzer_eval(globalNSString2); // expected-warning{{TRUE}} +} + +// Nested typedefs should work as well. +typedef const CFStringRef str1; +typedef str1 str2; +extern str2 globalStr2; +void testNestedTypedefs() { + clang_analyzer_eval(globalStr2); // expected-warning{{TRUE}} +} + +// And for NSString *. +typedef NSString *const nstr1; +typedef nstr1 nstr2; +extern nstr2 nglobalStr2; +void testNestedTypedefsForNSString() { + clang_analyzer_eval(nglobalStr2); // expected-warning{{TRUE}} +} + +// And for CFBooleanRefs. +extern const CFBooleanRef kBool; +void testNonnullBool() { + clang_analyzer_eval(kBool); // expected-warning{{TRUE}} +} + +// And again, only for const one. +extern CFBooleanRef kBoolMutable; +void testNonnullNonconstBool() { + clang_analyzer_eval(kBoolMutable); // expected-warning{{UNKNOWN}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/null-deref-ps.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/null-deref-ps.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/null-deref-ps.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/null-deref-ps.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-purge=none -verify %s -Wno-error=return-type -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -verify %s -Wno-error=return-type +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-purge=none -verify %s -Wno-error=return-type +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -verify %s -Wno-error=return-type typedef unsigned uintptr_t; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/objc-boxing.m llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/objc-boxing.m --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/objc-boxing.m 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/objc-boxing.m 2017-10-17 14:41:55.000000000 +0000 @@ -5,6 +5,16 @@ typedef signed char BOOL; typedef long NSInteger; typedef unsigned long NSUInteger; + +@protocol NSObject +@end +@interface NSObject {} +@end +@protocol NSCopying +@end +@protocol NSCoding +@end + @interface NSString @end @interface NSString (NSStringExtensionMethods) + (id)stringWithUTF8String:(const char *)nullTerminatedCString; @@ -28,7 +38,15 @@ + (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ; @end +@interface NSValue : NSObject +- (void)getValue:(void *)value; ++ (NSValue *)valueWithBytes:(const void *)value + objCType:(const char *)type; +@end +typedef typeof(sizeof(int)) size_t; +extern void *malloc(size_t); +extern void free(void *); extern char *strdup(const char *str); id constant_string() { @@ -39,6 +57,23 @@ return @(strdup("boxed dynamic string")); // expected-warning{{Potential memory leak}} } +typedef struct __attribute__((objc_boxable)) { + const char *str; +} BoxableStruct; + +id leak_within_boxed_struct() { + BoxableStruct bs; + bs.str = strdup("dynamic string"); // The duped string shall be owned by val. + NSValue *val = @(bs); // no-warning + return val; +} + +id leak_of_boxed_struct() { + BoxableStruct *bs = malloc(sizeof(BoxableStruct)); // The pointer stored in bs isn't owned by val. + NSValue *val = @(*bs); // expected-warning{{Potential leak of memory pointed to by 'bs'}} + return val; +} + id const_char_pointer(int *x) { if (x) return @(3); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/objc-encode.m llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/objc-encode.m --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/objc-encode.m 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/objc-encode.m 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=debug.ExprInspection -verify %s +// expected-no-diagnostics + +void clang_analyzer_eval(int); + +// rdar://problem/34831581: Used to crash. +void foo(void) { + char buf1[] = @encode(int **); +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/objc-for.m llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/objc-for.m --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/objc-for.m 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/objc-for.m 2017-10-17 14:41:55.000000000 +0000 @@ -1,6 +1,7 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify %s void clang_analyzer_eval(int); +void clang_analyzer_warnIfReached(); #define nil ((id)0) @@ -20,11 +21,13 @@ @interface NSArray : NSObject - (NSUInteger)count; - (NSEnumerator *)objectEnumerator; ++ (NSArray *)arrayWithObjects:(const id [])objects count:(NSUInteger)count; @end @interface NSDictionary : NSObject - (NSUInteger)count; - (id)objectForKey:(id)key; ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id /* */ [])keys count:(NSUInteger)count; @end @interface NSDictionary (SomeCategory) @@ -324,3 +327,19 @@ for (id key in array) clang_analyzer_eval(0); // expected-warning{{FALSE}} } + +NSArray *globalArray; +NSDictionary *globalDictionary; +void boxedArrayEscape(NSMutableArray *array) { + if ([array count]) + return; + globalArray = @[array]; + for (id key in array) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + + if ([array count]) + return; + globalDictionary = @{ @"array" : array }; + for (id key in array) + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/pointer-arithmetic.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/pointer-arithmetic.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/pointer-arithmetic.c 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/pointer-arithmetic.c 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s + +int test1() { + int *p = (int *)sizeof(int); + p -= 1; + return *p; // expected-warning {{Dereference of null pointer}} +} + +int test2() { + int *p = (int *)sizeof(int); + p -= 2; + p += 1; + return *p; // expected-warning {{Dereference of null pointer}} +} + +int test3() { + int *p = (int *)sizeof(int); + p++; + p--; + p--; + return *p; // expected-warning {{Dereference of null pointer}} +} + +int test4() { + // This is a special case where pointer arithmetic is not calculated to + // preserve useful warnings on dereferences of null pointers. + int *p = 0; + p += 1; + return *p; // expected-warning {{Dereference of null pointer}} +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/retain-release.mm llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/retain-release.mm --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/retain-release.mm 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/retain-release.mm 2017-10-17 14:41:55.000000000 +0000 @@ -463,3 +463,10 @@ // rdar://34210609 void _() { _(); }; // no-warning + +// Do not assume that IOBSDNameMatching increments a reference counter, +// unless return type is CFMutableDictionaryRef. +void* IOBSDNameMatching(); +void rdar33832412() { + void* x = IOBSDNameMatching(); // no-warning +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/retain-release-safe.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/retain-release-safe.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Analysis/retain-release-safe.c 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Analysis/retain-release-safe.c 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,72 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.RetainCount -verify %s + +#pragma clang arc_cf_code_audited begin +typedef const void * CFTypeRef; +extern CFTypeRef CFRetain(CFTypeRef cf); +extern void CFRelease(CFTypeRef cf); +#pragma clang arc_cf_code_audited end + +#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) +#define CF_CONSUMED __attribute__((cf_consumed)) + +extern CFTypeRef CFCreate() CF_RETURNS_RETAINED; + +// A "safe" variant of CFRetain that doesn't crash when a null pointer is +// retained. This is often defined by users in a similar manner. The +// CF_RETURNS_RETAINED annotation is misleading here, because the function +// is not supposed to return an object with a +1 retain count. Instead, it +// is supposed to return an object with +(N+1) retain count, where N is +// the original retain count of 'cf'. However, there is no good annotation +// to use in this case, and it is pointless to provide such annotation +// because the only use cases would be CFRetain and SafeCFRetain. +// So instead we teach the analyzer to be able to accept such code +// and ignore the misplaced annotation. +CFTypeRef SafeCFRetain(CFTypeRef cf) CF_RETURNS_RETAINED { + if (cf) { + return CFRetain(cf); + } + return cf; +} + +// A "safe" variant of CFRelease that doesn't crash when a null pointer is +// released. The CF_CONSUMED annotation seems reasonable here. +void SafeCFRelease(CFTypeRef CF_CONSUMED cf) { + if (cf) + CFRelease(cf); // no-warning (when inlined) +} + +void escape(CFTypeRef cf); + +void makeSureTestsWork() { + CFTypeRef cf = CFCreate(); + CFRelease(cf); + CFRelease(cf); // expected-warning{{Reference-counted object is used after it is released}} +} + +// Make sure we understand that the second SafeCFRetain doesn't return an +// object with +1 retain count, which we won't be able to release twice. +void falseOverrelease(CFTypeRef cf) { + SafeCFRetain(cf); + SafeCFRetain(cf); + SafeCFRelease(cf); + SafeCFRelease(cf); // no-warning after inlining this. +} + +// Regular CFRelease() should behave similarly. +void sameWithNormalRelease(CFTypeRef cf) { + SafeCFRetain(cf); + SafeCFRetain(cf); + CFRelease(cf); + CFRelease(cf); // no-warning +} + +// Make sure we understand that the second SafeCFRetain doesn't return an +// object with +1 retain count, which would no longer be owned by us after +// it escapes to escape() and released once. +void falseReleaseNotOwned(CFTypeRef cf) { + SafeCFRetain(cf); + SafeCFRetain(cf); + escape(cf); + SafeCFRelease(cf); + SafeCFRelease(cf); // no-warning after inlining this. +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/adc-builtins.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/adc-builtins.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/adc-builtins.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/adc-builtins.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,6 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s - -#define __MM_MALLOC_H +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s #include diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/arm64-microsoft-intrinsics.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/arm64-microsoft-intrinsics.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/arm64-microsoft-intrinsics.c 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/arm64-microsoft-intrinsics.c 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm -o - %s \ +// RUN: | FileCheck %s -check-prefix CHECK-MSVC + +// RUN: not %clang_cc1 -triple arm64-linux -Werror -S -o /dev/null %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-LINUX + +void check__dmb(void) { + __dmb(0); +} + +// CHECK-MSVC: @llvm.aarch64.dmb(i32 0) +// CHECK-LINUX: error: implicit declaration of function '__dmb' + +void check__dsb(void) { + __dsb(0); +} + +// CHECK-MSVC: @llvm.aarch64.dsb(i32 0) +// CHECK-LINUX: error: implicit declaration of function '__dsb' + +void check__isb(void) { + __isb(0); +} + +// CHECK-MSVC: @llvm.aarch64.isb(i32 0) +// CHECK-LINUX: error: implicit declaration of function '__isb' diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/arm-metadata.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/arm-metadata.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/arm-metadata.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/arm-metadata.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s | FileCheck -check-prefix=DEFAULT %s // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fshort-enums | FileCheck -check-prefix=SHORT-ENUM %s -// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fshort-wchar | FileCheck -check-prefix=SHORT-WCHAR %s +// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fwchar-type=short -fno-signed-wchar | FileCheck -check-prefix=SHORT-WCHAR %s // DEFAULT: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4} // DEFAULT: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 4} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/avx512ifmavl-builtins.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/avx512ifmavl-builtins.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/avx512ifmavl-builtins.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/avx512ifmavl-builtins.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,6 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512ifma -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s - -#define __MM_MALLOC_H +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-apple-darwin -target-feature +avx512ifma -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s #include diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/blocks-opencl.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/blocks-opencl.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/blocks-opencl.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/blocks-opencl.cl 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -O0 %s -ffake-address-space-map -emit-llvm -o - -fblocks -triple x86_64-unknown-unknown | FileCheck %s -// This used to crash due to trying to generate a bitcase from a cstring -// in the constant address space to i8* in AS0. - -void dummy(float (^const op)(float)) { -} - -// CHECK: i8 addrspace(2)* getelementptr inbounds ([9 x i8], [9 x i8] addrspace(2)* @.str, i32 0, i32 0) - -kernel void test_block() -{ - float (^const X)(float) = ^(float x) { - return x + 42.0f; - }; - dummy(X); -} - diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtin-clflushopt.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtin-clflushopt.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtin-clflushopt.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtin-clflushopt.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +clflushopt -emit-llvm -o - -Wall -Werror | FileCheck %s -#define __MM_MALLOC_H +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-apple-darwin -target-feature +clflushopt -emit-llvm -o - -Wall -Werror | FileCheck %s + +#include -#include void test_mm_clflushopt(char * __m) { //CHECK-LABEL: @test_mm_clflushopt //CHECK: @llvm.x86.clflushopt diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtin-clwb.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtin-clwb.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtin-clwb.c 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtin-clwb.c 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-apple-darwin -target-feature +clwb -emit-llvm -o - -Wall -Werror | FileCheck %s + +#include + +void test_mm_clwb(const void *__m) { + //CHECK-LABEL: @test_mm_clwb + //CHECK: @llvm.x86.clwb + _mm_clwb(__m); +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtin-clzero.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtin-clzero.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtin-clzero.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtin-clzero.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +clzero -emit-llvm -o - -Wall -Werror | FileCheck %s -#define __MM_MALLOC_H +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-apple-darwin -target-feature +clzero -emit-llvm -o - -Wall -Werror | FileCheck %s #include + void test_mm_clzero(void * __m) { //CHECK-LABEL: @test_mm_clzero //CHECK: @llvm.x86.clzero diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtins.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtins.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtins.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtins.c 2017-10-17 14:41:55.000000000 +0000 @@ -378,229 +378,385 @@ #ifdef __x86_64__ // CHECK-LABEL: define void @test_builtin_os_log -// CHECK: (i8* [[BUF:%.*]], i32 [[I:%.*]], i8* [[DATA:%.*]]) +// CHECK: (i8* %[[BUF:.*]], i32 %[[I:.*]], i8* %[[DATA:.*]]) void test_builtin_os_log(void *buf, int i, const char *data) { volatile int len; - // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8 - // CHECK: store i32 [[I]], i32* [[I_ADDR:%.*]], align 4 - // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8 + // CHECK: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[I_ADDR:.*]] = alloca i32, align 4 + // CHECK: %[[DATA_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[LEN:.*]] = alloca i32, align 4 + // CHECK: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK: store i32 %[[I]], i32* %[[I_ADDR]], align 4 + // CHECK: store i8* %[[DATA]], i8** %[[DATA_ADDR]], align 8 - // CHECK: store volatile i32 34 + // CHECK: store volatile i32 34, i32* %[[LEN]] len = __builtin_os_log_format_buffer_size("%d %{public}s %{private}.16P", i, data, data); - // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]] - // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0 - // CHECK: store i8 3, i8* [[SUMMARY]] - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1 - // CHECK: store i8 4, i8* [[NUM_ARGS]] - // - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2 - // CHECK: store i8 0, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3 - // CHECK: store i8 4, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4 - // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32* - // CHECK: [[I2:%.*]] = load i32, i32* [[I_ADDR]] - // CHECK: store i32 [[I2]], i32* [[ARG1_INT]] - - // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 8 - // CHECK: store i8 34, i8* [[ARG2_DESC]] - // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 9 - // CHECK: store i8 8, i8* [[ARG2_SIZE]] - // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 10 - // CHECK: [[ARG2_PTR:%.*]] = bitcast i8* [[ARG2]] to i8** - // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA_ADDR]] - // CHECK: store i8* [[DATA2]], i8** [[ARG2_PTR]] - - // CHECK: [[ARG3_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 18 - // CHECK: store i8 17, i8* [[ARG3_DESC]] - // CHECK: [[ARG3_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 19 - // CHECK: store i8 4, i8* [[ARG3_SIZE]] - // CHECK: [[ARG3:%.*]] = getelementptr i8, i8* [[BUF2]], i64 20 - // CHECK: [[ARG3_INT:%.*]] = bitcast i8* [[ARG3]] to i32* - // CHECK: store i32 16, i32* [[ARG3_INT]] - - // CHECK: [[ARG4_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 24 - // CHECK: store i8 49, i8* [[ARG4_DESC]] - // CHECK: [[ARG4_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 25 - // CHECK: store i8 8, i8* [[ARG4_SIZE]] - // CHECK: [[ARG4:%.*]] = getelementptr i8, i8* [[BUF2]], i64 26 - // CHECK: [[ARG4_PTR:%.*]] = bitcast i8* [[ARG4]] to i8** - // CHECK: [[DATA3:%.*]] = load i8*, i8** [[DATA_ADDR]] - // CHECK: store i8* [[DATA3]], i8** [[ARG4_PTR]] - + // CHECK: %[[V1:.*]] = load i8*, i8** %[[BUF_ADDR]] + // CHECK: %[[V2:.*]] = load i32, i32* %[[I_ADDR]] + // CHECK: %[[V3:.*]] = load i8*, i8** %[[DATA_ADDR]] + // CHECK: %[[V4:.*]] = ptrtoint i8* %[[V3]] to i64 + // CHECK: %[[V5:.*]] = load i8*, i8** %[[DATA_ADDR]] + // CHECK: %[[V6:.*]] = ptrtoint i8* %[[V5]] to i64 + // CHECK: call void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49(i8* %[[V1]], i32 %[[V2]], i64 %[[V4]], i32 16, i64 %[[V6]]) __builtin_os_log_format(buf, "%d %{public}s %{private}.16P", i, data, data); } -// CHECK-LABEL: define void @test_builtin_os_log_errno -// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]]) -void test_builtin_os_log_errno(void *buf, const char *data) { - volatile int len; - // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8 - // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8 +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49 +// CHECK: (i8* %[[BUFFER:.*]], i32 %[[ARG0:.*]], i64 %[[ARG1:.*]], i32 %[[ARG2:.*]], i64 %[[ARG3:.*]]) - // CHECK: store volatile i32 2 - len = __builtin_os_log_format_buffer_size("%S"); - - // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]] - // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0 - // CHECK: store i8 2, i8* [[SUMMARY]] - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1 - // CHECK: store i8 1, i8* [[NUM_ARGS]] - - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2 - // CHECK: store i8 96, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3 - // CHECK: store i8 0, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4 - // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32* - // CHECK: store i32 0, i32* [[ARG1_INT]] - - __builtin_os_log_format(buf, "%m"); -} +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[ARG0_ADDR:.*]] = alloca i32, align 4 +// CHECK: %[[ARG1_ADDR:.*]] = alloca i64, align 8 +// CHECK: %[[ARG2_ADDR:.*]] = alloca i32, align 4 +// CHECK: %[[ARG3_ADDR:.*]] = alloca i64, align 8 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: store i32 %[[ARG0]], i32* %[[ARG0_ADDR]], align 4 +// CHECK: store i64 %[[ARG1]], i64* %[[ARG1_ADDR]], align 8 +// CHECK: store i32 %[[ARG2]], i32* %[[ARG2_ADDR]], align 4 +// CHECK: store i64 %[[ARG3]], i64* %[[ARG3_ADDR]], align 8 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 3, i8* %[[SUMMARY]], align 1 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 4, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 0, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 4, i8* %[[ARGSIZE]], align 1 +// CHECK: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i32* +// CHECK: %[[V0:.*]] = load i32, i32* %[[ARG0_ADDR]], align 4 +// CHECK: store i32 %[[V0]], i32* %[[ARGDATACAST]], align 1 +// CHECK: %[[ARGDESCRIPTOR1:.*]] = getelementptr i8, i8* %[[BUF]], i64 8 +// CHECK: store i8 34, i8* %[[ARGDESCRIPTOR1]], align 1 +// CHECK: %[[ARGSIZE2:.*]] = getelementptr i8, i8* %[[BUF]], i64 9 +// CHECK: store i8 8, i8* %[[ARGSIZE2]], align 1 +// CHECK: %[[ARGDATA3:.*]] = getelementptr i8, i8* %[[BUF]], i64 10 +// CHECK: %[[ARGDATACAST4:.*]] = bitcast i8* %[[ARGDATA3]] to i64* +// CHECK: %[[V1:.*]] = load i64, i64* %[[ARG1_ADDR]], align 8 +// CHECK: store i64 %[[V1]], i64* %[[ARGDATACAST4]], align 1 +// CHECK: %[[ARGDESCRIPTOR5:.*]] = getelementptr i8, i8* %[[BUF]], i64 18 +// CHECK: store i8 17, i8* %[[ARGDESCRIPTOR5]], align 1 +// CHECK: %[[ARGSIZE6:.*]] = getelementptr i8, i8* %[[BUF]], i64 19 +// CHECK: store i8 4, i8* %[[ARGSIZE6]], align 1 +// CHECK: %[[ARGDATA7:.*]] = getelementptr i8, i8* %[[BUF]], i64 20 +// CHECK: %[[ARGDATACAST8:.*]] = bitcast i8* %[[ARGDATA7]] to i32* +// CHECK: %[[V2:.*]] = load i32, i32* %[[ARG2_ADDR]], align 4 +// CHECK: store i32 %[[V2]], i32* %[[ARGDATACAST8]], align 1 +// CHECK: %[[ARGDESCRIPTOR9:.*]] = getelementptr i8, i8* %[[BUF]], i64 24 +// CHECK: store i8 49, i8* %[[ARGDESCRIPTOR9]], align 1 +// CHECK: %[[ARGSIZE10:.*]] = getelementptr i8, i8* %[[BUF]], i64 25 +// CHECK: store i8 8, i8* %[[ARGSIZE10]], align 1 +// CHECK: %[[ARGDATA11:.*]] = getelementptr i8, i8* %[[BUF]], i64 26 +// CHECK: %[[ARGDATACAST12:.*]] = bitcast i8* %[[ARGDATA11]] to i64* +// CHECK: %[[V3:.*]] = load i64, i64* %[[ARG3_ADDR]], align 8 +// CHECK: store i64 %[[V3]], i64* %[[ARGDATACAST12]], align 1 // CHECK-LABEL: define void @test_builtin_os_log_wide -// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]], i32* [[STR:%.*]]) +// CHECK: (i8* %[[BUF:.*]], i8* %[[DATA:.*]], i32* %[[STR:.*]]) typedef int wchar_t; void test_builtin_os_log_wide(void *buf, const char *data, wchar_t *str) { volatile int len; - // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8 - // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8 - // CHECK: store i32* [[STR]], i32** [[STR_ADDR:%.*]], - // CHECK: store volatile i32 12 + // CHECK: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[DATA_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[STR_ADDR:.*]] = alloca i32*, align 8 + // CHECK: %[[LEN:.*]] = alloca i32, align 4 + // CHECK: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK: store i8* %[[DATA]], i8** %[[DATA_ADDR]], align 8 + // CHECK: store i32* %[[STR]], i32** %[[STR_ADDR]], align 8 + + // CHECK: store volatile i32 12, i32* %[[LEN]], align 4 len = __builtin_os_log_format_buffer_size("%S", str); - // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]] - // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0 - // CHECK: store i8 2, i8* [[SUMMARY]] - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1 - // CHECK: store i8 1, i8* [[NUM_ARGS]] - - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2 - // CHECK: store i8 80, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3 - // CHECK: store i8 8, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4 - // CHECK: [[ARG1_PTR:%.*]] = bitcast i8* [[ARG1]] to i32** - // CHECK: [[STR2:%.*]] = load i32*, i32** [[STR_ADDR]] - // CHECK: store i32* [[STR2]], i32** [[ARG1_PTR]] + // CHECK: %[[V1:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8 + // CHECK: %[[V2:.*]] = load i32*, i32** %[[STR_ADDR]], align 8 + // CHECK: %[[V3:.*]] = ptrtoint i32* %[[V2]] to i64 + // CHECK: call void @__os_log_helper_1_2_1_8_80(i8* %[[V1]], i64 %[[V3]]) __builtin_os_log_format(buf, "%S", str); } +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_1_8_80 +// CHECK: (i8* %[[BUFFER:.*]], i64 %[[ARG0:.*]]) + +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[ARG0_ADDR:.*]] = alloca i64, align 8 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: store i64 %[[ARG0]], i64* %[[ARG0_ADDR]], align 8 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 2, i8* %[[SUMMARY]], align 1 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 1, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 80, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 8, i8* %[[ARGSIZE]], align 1 +// CHECK: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i64* +// CHECK: %[[V0:.*]] = load i64, i64* %[[ARG0_ADDR]], align 8 +// CHECK: store i64 %[[V0]], i64* %[[ARGDATACAST]], align 1 + // CHECK-LABEL: define void @test_builtin_os_log_precision_width -// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]], i32 [[PRECISION:%.*]], i32 [[WIDTH:%.*]]) +// CHECK: (i8* %[[BUF:.*]], i8* %[[DATA:.*]], i32 %[[PRECISION:.*]], i32 %[[WIDTH:.*]]) void test_builtin_os_log_precision_width(void *buf, const char *data, int precision, int width) { volatile int len; - // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8 - // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8 - // CHECK: store i32 [[PRECISION]], i32* [[PRECISION_ADDR:%.*]], align 4 - // CHECK: store i32 [[WIDTH]], i32* [[WIDTH_ADDR:%.*]], align 4 + // CHECK: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[DATA_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[PRECISION_ADDR:.*]] = alloca i32, align 4 + // CHECK: %[[WIDTH_ADDR:.*]] = alloca i32, align 4 + // CHECK: %[[LEN:.*]] = alloca i32, align 4 + // CHECK: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK: store i8* %[[DATA]], i8** %[[DATA_ADDR]], align 8 + // CHECK: store i32 %[[PRECISION]], i32* %[[PRECISION_ADDR]], align 4 + // CHECK: store i32 %[[WIDTH]], i32* %[[WIDTH_ADDR]], align 4 - // CHECK: store volatile i32 24, + // CHECK: store volatile i32 24, i32* %[[LEN]], align 4 len = __builtin_os_log_format_buffer_size("Hello %*.*s World", precision, width, data); - // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]] - // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0 - // CHECK: store i8 2, i8* [[SUMMARY]] - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1 - // CHECK: store i8 3, i8* [[NUM_ARGS]] - - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2 - // CHECK: store i8 0, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3 - // CHECK: store i8 4, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4 - // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32* - // CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[PRECISION_ADDR]] - // CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]] - - // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 8 - // CHECK: store i8 16, i8* [[ARG2_DESC]] - // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 9 - // CHECK: store i8 4, i8* [[ARG2_SIZE]] - // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 10 - // CHECK: [[ARG2_INT:%.*]] = bitcast i8* [[ARG2]] to i32* - // CHECK: [[ARG2_VAL:%.*]] = load i32, i32* [[WIDTH_ADDR]] - // CHECK: store i32 [[ARG2_VAL]], i32* [[ARG2_INT]] - - // CHECK: [[ARG3_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 14 - // CHECK: store i8 32, i8* [[ARG3_DESC]] - // CHECK: [[ARG3_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 15 - // CHECK: store i8 8, i8* [[ARG3_SIZE]] - // CHECK: [[ARG3:%.*]] = getelementptr i8, i8* [[BUF2]], i64 16 - // CHECK: [[ARG3_PTR:%.*]] = bitcast i8* [[ARG3]] to i8** - // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA_ADDR]] - // CHECK: store i8* [[DATA2]], i8** [[ARG3_PTR]] - + // CHECK: %[[V1:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8 + // CHECK: %[[V2:.*]] = load i32, i32* %[[PRECISION_ADDR]], align 4 + // CHECK: %[[V3:.*]] = load i32, i32* %[[WIDTH_ADDR]], align 4 + // CHECK: %[[V4:.*]] = load i8*, i8** %[[DATA_ADDR]], align 8 + // CHECK: %[[V5:.*]] = ptrtoint i8* %[[V4]] to i64 + // CHECK: call void @__os_log_helper_1_2_3_4_0_4_16_8_32(i8* %[[V1]], i32 %[[V2]], i32 %[[V3]], i64 %[[V5]]) __builtin_os_log_format(buf, "Hello %*.*s World", precision, width, data); } +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_3_4_0_4_16_8_32 +// CHECK: (i8* %[[BUFFER:.*]], i32 %[[ARG0:.*]], i32 %[[ARG1:.*]], i64 %[[ARG2:.*]]) + +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[ARG0_ADDR:.*]] = alloca i32, align 4 +// CHECK: %[[ARG1_ADDR:.*]] = alloca i32, align 4 +// CHECK: %[[ARG2_ADDR:.*]] = alloca i64, align 8 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: store i32 %[[ARG0]], i32* %[[ARG0_ADDR]], align 4 +// CHECK: store i32 %[[ARG1]], i32* %[[ARG1_ADDR]], align 4 +// CHECK: store i64 %[[ARG2]], i64* %[[ARG2_ADDR]], align 8 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 2, i8* %[[SUMMARY]], align 1 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 3, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 0, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 4, i8* %[[ARGSIZE]], align 1 +// CHECK: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i32* +// CHECK: %[[V0:.*]] = load i32, i32* %[[ARG0_ADDR]], align 4 +// CHECK: store i32 %[[V0]], i32* %[[ARGDATACAST]], align 1 +// CHECK: %[[ARGDESCRIPTOR1:.*]] = getelementptr i8, i8* %[[BUF]], i64 8 +// CHECK: store i8 16, i8* %[[ARGDESCRIPTOR1]], align 1 +// CHECK: %[[ARGSIZE2:.*]] = getelementptr i8, i8* %[[BUF]], i64 9 +// CHECK: store i8 4, i8* %[[ARGSIZE2]], align 1 +// CHECK: %[[ARGDATA3:.*]] = getelementptr i8, i8* %[[BUF]], i64 10 +// CHECK: %[[ARGDATACAST4:.*]] = bitcast i8* %[[ARGDATA3]] to i32* +// CHECK: %[[V1:.*]] = load i32, i32* %[[ARG1_ADDR]], align 4 +// CHECK: store i32 %[[V1]], i32* %[[ARGDATACAST4]], align 1 +// CHECK: %[[ARGDESCRIPTOR5:.*]] = getelementptr i8, i8* %[[BUF]], i64 14 +// CHECK: store i8 32, i8* %[[ARGDESCRIPTOR5]], align 1 +// CHECK: %[[ARGSIZE6:.*]] = getelementptr i8, i8* %[[BUF]], i64 15 +// CHECK: store i8 8, i8* %[[ARGSIZE6]], align 1 +// CHECK: %[[ARGDATA7:.*]] = getelementptr i8, i8* %[[BUF]], i64 16 +// CHECK: %[[ARGDATACAST8:.*]] = bitcast i8* %[[ARGDATA7]] to i64* +// CHECK: %[[V2:.*]] = load i64, i64* %[[ARG2_ADDR]], align 8 +// CHECK: store i64 %[[V2]], i64* %[[ARGDATACAST8]], align 1 + // CHECK-LABEL: define void @test_builtin_os_log_invalid -// CHECK: (i8* [[BUF:%.*]], i32 [[DATA:%.*]]) +// CHECK: (i8* %[[BUF:.*]], i32 %[[DATA:.*]]) void test_builtin_os_log_invalid(void *buf, int data) { volatile int len; - // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8 - // CHECK: store i32 [[DATA]], i32* [[DATA_ADDR:%.*]] + // CHECK: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[DATA_ADDR:.*]] = alloca i32, align 4 + // CHECK: %[[LEN:.*]] = alloca i32, align 4 + // CHECK: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK: store i32 %[[DATA]], i32* %[[DATA_ADDR]], align 4 - // CHECK: store volatile i32 8, + // CHECK: store volatile i32 8, i32* %[[LEN]], align 4 len = __builtin_os_log_format_buffer_size("invalid specifier %: %d even a trailing one%", data); - // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]] - // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0 - // CHECK: store i8 0, i8* [[SUMMARY]] - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1 - // CHECK: store i8 1, i8* [[NUM_ARGS]] - - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2 - // CHECK: store i8 0, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3 - // CHECK: store i8 4, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4 - // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32* - // CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[DATA_ADDR]] - // CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]] + // CHECK: %[[V1:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8 + // CHECK: %[[V2:.*]] = load i32, i32* %[[DATA_ADDR]], align 4 + // CHECK: call void @__os_log_helper_1_0_1_4_0(i8* %[[V1]], i32 %[[V2]]) __builtin_os_log_format(buf, "invalid specifier %: %d even a trailing one%", data); } +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_0_1_4_0 +// CHECK: (i8* %[[BUFFER:.*]], i32 %[[ARG0:.*]]) + +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[ARG0_ADDR:.*]] = alloca i32, align 4 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: store i32 %[[ARG0]], i32* %[[ARG0_ADDR]], align 4 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 0, i8* %[[SUMMARY]], align 1 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 1, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 0, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 4, i8* %[[ARGSIZE]], align 1 +// CHECK: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i32* +// CHECK: %[[V0:.*]] = load i32, i32* %[[ARG0_ADDR]], align 4 +// CHECK: store i32 %[[V0]], i32* %[[ARGDATACAST]], align 1 + // CHECK-LABEL: define void @test_builtin_os_log_percent -// CHECK: (i8* [[BUF:%.*]], i8* [[DATA1:%.*]], i8* [[DATA2:%.*]]) +// CHECK: (i8* %[[BUF:.*]], i8* %[[DATA1:.*]], i8* %[[DATA2:.*]]) // Check that the %% which does not consume any argument is correctly handled void test_builtin_os_log_percent(void *buf, const char *data1, const char *data2) { volatile int len; - // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8 - // CHECK: store i8* [[DATA1]], i8** [[DATA1_ADDR:%.*]], align 8 - // CHECK: store i8* [[DATA2]], i8** [[DATA2_ADDR:%.*]], align 8 - // CHECK: store volatile i32 22 + // CHECK: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[DATA1_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[DATA2_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[LEN:.*]] = alloca i32, align 4 + // CHECK: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK: store i8* %[[DATA1]], i8** %[[DATA1_ADDR]], align 8 + // CHECK: store i8* %[[DATA2]], i8** %[[DATA2_ADDR]], align 8 + // CHECK: store volatile i32 22, i32* %[[LEN]], align 4 + len = __builtin_os_log_format_buffer_size("%s %% %s", data1, data2); - // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]] - // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0 - // CHECK: store i8 2, i8* [[SUMMARY]] - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1 - // CHECK: store i8 2, i8* [[NUM_ARGS]] - // - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2 - // CHECK: store i8 32, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3 - // CHECK: store i8 8, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4 - // CHECK: [[ARG1_PTR:%.*]] = bitcast i8* [[ARG1]] to i8** - // CHECK: [[DATA1:%.*]] = load i8*, i8** [[DATA1_ADDR]] - // CHECK: store i8* [[DATA1]], i8** [[ARG1_PTR]] - // - // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 12 - // CHECK: store i8 32, i8* [[ARG2_DESC]] - // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 13 - // CHECK: store i8 8, i8* [[ARG2_SIZE]] - // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 14 - // CHECK: [[ARG2_PTR:%.*]] = bitcast i8* [[ARG2]] to i8** - // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA2_ADDR]] - // CHECK: store i8* [[DATA2]], i8** [[ARG2_PTR]] + // CHECK: %[[V1:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8 + // CHECK: %[[V2:.*]] = load i8*, i8** %[[DATA1_ADDR]], align 8 + // CHECK: %[[V3:.*]] = ptrtoint i8* %[[V2]] to i64 + // CHECK: %[[V4:.*]] = load i8*, i8** %[[DATA2_ADDR]], align 8 + // CHECK: %[[V5:.*]] = ptrtoint i8* %[[V4]] to i64 + // CHECK: call void @__os_log_helper_1_2_2_8_32_8_32(i8* %[[V1]], i64 %[[V3]], i64 %[[V5]]) + __builtin_os_log_format(buf, "%s %% %s", data1, data2); } -#endif \ No newline at end of file +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_2_8_32_8_32 +// CHECK: (i8* %[[BUFFER:.*]], i64 %[[ARG0:.*]], i64 %[[ARG1:.*]]) + +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[ARG0_ADDR:.*]] = alloca i64, align 8 +// CHECK: %[[ARG1_ADDR:.*]] = alloca i64, align 8 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: store i64 %[[ARG0]], i64* %[[ARG0_ADDR]], align 8 +// CHECK: store i64 %[[ARG1]], i64* %[[ARG1_ADDR]], align 8 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 2, i8* %[[SUMMARY]], align 1 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 2, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 32, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 8, i8* %[[ARGSIZE]], align 1 +// CHECK: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i64* +// CHECK: %[[V0:.*]] = load i64, i64* %[[ARG0_ADDR]], align 8 +// CHECK: store i64 %[[V0]], i64* %[[ARGDATACAST]], align 1 +// CHECK: %[[ARGDESCRIPTOR1:.*]] = getelementptr i8, i8* %[[BUF]], i64 12 +// CHECK: store i8 32, i8* %[[ARGDESCRIPTOR1]], align 1 +// CHECK: %[[ARGSIZE2:.*]] = getelementptr i8, i8* %[[BUF]], i64 13 +// CHECK: store i8 8, i8* %[[ARGSIZE2]], align 1 +// CHECK: %[[ARGDATA3:.*]] = getelementptr i8, i8* %[[BUF]], i64 14 +// CHECK: %[[ARGDATACAST4:.*]] = bitcast i8* %[[ARGDATA3]] to i64* +// CHECK: %[[V1:.*]] = load i64, i64* %[[ARG1_ADDR]], align 8 +// CHECK: store i64 %[[V1]], i64* %[[ARGDATACAST4]], align 1 + +// Check that the following two functions call the same helper function. + +// CHECK-LABEL: define void @test_builtin_os_log_merge_helper0 +// CHECK: call void @__os_log_helper_1_0_2_4_0_8_0( +void test_builtin_os_log_merge_helper0(void *buf, int i, double d) { + __builtin_os_log_format(buf, "%d %f", i, d); +} + +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_0_2_4_0_8_0( + +// CHECK-LABEL: define void @test_builtin_os_log_merge_helper1 +// CHECK: call void @__os_log_helper_1_0_2_4_0_8_0( +void test_builtin_os_log_merge_helper1(void *buf, unsigned u, long long ll) { + __builtin_os_log_format(buf, "%u %lld", u, ll); +} + +// Check that this function doesn't write past the end of array 'buf'. + +// CHECK-LABEL: define void @test_builtin_os_log_errno +void test_builtin_os_log_errno() { + // CHECK: %[[VLA:.*]] = alloca i8, i64 4, align 16 + // CHECK: call void @__os_log_helper_16_2_1_0_96(i8* %[[VLA]]) + + char buf[__builtin_os_log_format_buffer_size("%m")]; + __builtin_os_log_format(buf, "%m"); +} + +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_16_2_1_0_96 +// CHECK: (i8* %[[BUFFER:.*]]) + +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 2, i8* %[[SUMMARY]], align 16 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 1, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 2 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 0, i8* %[[ARGSIZE]], align 1 +// CHECK-NEXT: ret void + +// CHECK-LABEL: define void @test_builtin_os_log_long_double +// CHECK: (i8* %[[BUF:.*]], x86_fp80 %[[LD:.*]]) +void test_builtin_os_log_long_double(void *buf, long double ld) { + // CHECK: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK: %[[LD_ADDR:.*]] = alloca x86_fp80, align 16 + // CHECK: %[[COERCE:.*]] = alloca i128, align 16 + // CHECK: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK: store x86_fp80 %[[LD]], x86_fp80* %[[LD_ADDR]], align 16 + // CHECK: %[[V0:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8 + // CHECK: %[[V1:.*]] = load x86_fp80, x86_fp80* %[[LD_ADDR]], align 16 + // CHECK: %[[V2:.*]] = bitcast x86_fp80 %[[V1]] to i80 + // CHECK: %[[V3:.*]] = zext i80 %[[V2]] to i128 + // CHECK: store i128 %[[V3]], i128* %[[COERCE]], align 16 + // CHECK: %[[V4:.*]] = bitcast i128* %[[COERCE]] to { i64, i64 }* + // CHECK: %[[V5:.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* %[[V4]], i32 0, i32 0 + // CHECK: %[[V6:.*]] = load i64, i64* %[[V5]], align 16 + // CHECK: %[[V7:.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* %[[V4]], i32 0, i32 1 + // CHECK: %[[V8:.*]] = load i64, i64* %[[V7]], align 8 + // CHECK: call void @__os_log_helper_1_0_1_16_0(i8* %[[V0]], i64 %[[V6]], i64 %[[V8]]) + + __builtin_os_log_format(buf, "%Lf", ld); +} + +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_0_1_16_0 +// CHECK: (i8* %[[BUFFER:.*]], i64 %[[ARG0_COERCE0:.*]], i64 %[[ARG0_COERCE1:.*]]) + +// CHECK: %[[ARG0:.*]] = alloca i128, align 16 +// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[ARG0_ADDR:.*]] = alloca i128, align 16 +// CHECK: %[[V0:.*]] = bitcast i128* %[[ARG0]] to { i64, i64 }* +// CHECK: %[[V1:.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* %[[V0]], i32 0, i32 0 +// CHECK: store i64 %[[ARG0_COERCE0]], i64* %[[V1]], align 16 +// CHECK: %[[V2:.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* %[[V0]], i32 0, i32 1 +// CHECK: store i64 %[[ARG0_COERCE1]], i64* %[[V2]], align 8 +// CHECK: %[[ARG01:.*]] = load i128, i128* %[[ARG0]], align 16 +// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK: store i128 %[[ARG01]], i128* %[[ARG0_ADDR]], align 16 +// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK: store i8 0, i8* %[[SUMMARY]], align 1 +// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK: store i8 1, i8* %[[NUMARGS]], align 1 +// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK: store i8 0, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK: store i8 16, i8* %[[ARGSIZE]], align 1 +// CHECK: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i128* +// CHECK: %[[V3:.*]] = load i128, i128* %[[ARG0_ADDR]], align 16 +// CHECK: store i128 %[[V3]], i128* %[[ARGDATACAST]], align 1 + +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtins-nvptx-sm_70.cu llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtins-nvptx-sm_70.cu --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/builtins-nvptx-sm_70.cu 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/builtins-nvptx-sm_70.cu 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,166 @@ +// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_70 \ +// RUN: -fcuda-is-device -target-feature +ptx60 \ +// RUN: -S -emit-llvm -o - -x cuda %s \ +// RUN: | FileCheck -check-prefix=CHECK %s +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_60 \ +// RUN: -fcuda-is-device -S -o /dev/null -x cuda -verify %s + +#if !defined(CUDA_VERSION) +#define __device__ __attribute__((device)) +#define __global__ __attribute__((global)) +#define __shared__ __attribute__((shared)) +#define __constant__ __attribute__((constant)) + +typedef unsigned long long uint64_t; +#endif +// We have to keep all builtins that depend on particular target feature in the +// same function, because the codegen will stop after the very first function +// that encounters an error, so -verify will not be able to find errors in +// subsequent functions. + +// CHECK-LABEL: nvvm_wmma +__device__ void nvvm_wmma(int *src, int *dst, + float *fsrc, float *fdst, + int ldm) { + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.a.sync.row.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_ld_a' needs target feature ptx60}} + __hmma_m16n16k16_ld_a(dst, src, ldm, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.a.sync.col.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_ld_a' needs target feature ptx60}} + __hmma_m16n16k16_ld_a(dst, src+1, ldm, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.b.sync.row.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_ld_b' needs target feature ptx60}} + __hmma_m16n16k16_ld_b(dst, src, ldm, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.b.sync.col.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_ld_b' needs target feature ptx60}} + __hmma_m16n16k16_ld_b(dst, src+2, ldm, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.row.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature ptx60}} + __hmma_m16n16k16_ld_c_f16(dst, src, ldm, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.col.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature ptx60}} + __hmma_m16n16k16_ld_c_f16(dst, src, ldm, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.row.m16n16k16.stride.f32 + // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature ptx60}} + __hmma_m16n16k16_ld_c_f32(fdst, fsrc, ldm, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.col.m16n16k16.stride.f32 + // expected-error@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature ptx60}} + __hmma_m16n16k16_ld_c_f32(fdst, fsrc, ldm, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.row.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature ptx60}} + __hmma_m16n16k16_st_c_f16(dst, src, ldm, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.col.m16n16k16.stride.f16 + // expected-error@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature ptx60}} + __hmma_m16n16k16_st_c_f16(dst, src, ldm, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.row.m16n16k16.stride.f32 + // expected-error@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature ptx60}} + __hmma_m16n16k16_st_c_f32(fdst, fsrc, ldm, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.col.m16n16k16.stride.f32 + // expected-error@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature ptx60}} + __hmma_m16n16k16_st_c_f32(fdst, fsrc, ldm, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 0, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 0, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 1, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 1, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 2, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 2, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 3, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f16(dst, src, src, src, 3, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 0, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 0, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 1, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 1, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 2, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 2, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 3, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 3, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 0, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 0, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 1, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 1, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 2, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 2, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f16 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 3, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f16.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 3, 1); + + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 0, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 0, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 1, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 1, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 2, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 2, 1); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f32 + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 3, 0); + // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f32.satfinite + // expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}} + __hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 3, 1); +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/libcall-declarations.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/libcall-declarations.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/libcall-declarations.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/libcall-declarations.c 2017-10-17 14:41:55.000000000 +0000 @@ -312,314 +312,310 @@ F(__cospif), F(__tanpi), F(__tanpif), F(__exp10), F(__exp10f) }; -// CHECK-NOERRNO: declare double @atan2(double, double) [[NUW:#[0-9]+]] -// CHECK-NOERRNO: declare float @atan2f(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare i32 @abs(i32) [[NUW]] -// CHECK-NOERRNO: declare i64 @labs(i64) [[NUW]] -// CHECK-NOERRNO: declare i64 @llabs(i64) [[NUW]] -// CHECK-NOERRNO: declare double @copysign(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @copysignf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @fabs(double) [[NUW]] -// CHECK-NOERRNO: declare float @fabsf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @fabsl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @fmod(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @fmodf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @ldexp(double, i32) [[NUW]] -// CHECK-NOERRNO: declare float @ldexpf(float, i32) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NUW]] -// CHECK-NOERRNO: declare double @nan(i8*) [[NUW]] -// CHECK-NOERRNO: declare float @nanf(i8*) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @nanl(i8*) [[NUW]] -// CHECK-NOERRNO: declare double @pow(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @powf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @acos(double) [[NUW]] -// CHECK-NOERRNO: declare float @acosf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @acosl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @acosh(double) [[NUW]] -// CHECK-NOERRNO: declare float @acoshf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @acoshl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @asin(double) [[NUW]] -// CHECK-NOERRNO: declare float @asinf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @asinl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @asinh(double) [[NUW]] -// CHECK-NOERRNO: declare float @asinhf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @asinhl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @atan(double) [[NUW]] -// CHECK-NOERRNO: declare float @atanf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @atanl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @atanh(double) [[NUW]] -// CHECK-NOERRNO: declare float @atanhf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @atanhl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @cbrt(double) [[NUW]] -// CHECK-NOERRNO: declare float @cbrtf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @ceil(double) [[NUW]] -// CHECK-NOERRNO: declare float @ceilf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @ceill(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @cos(double) [[NUW]] -// CHECK-NOERRNO: declare float @cosf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @cosl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @cosh(double) [[NUW]] -// CHECK-NOERRNO: declare float @coshf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @coshl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @erf(double) [[NUW]] -// CHECK-NOERRNO: declare float @erff(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @erfl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @erfc(double) [[NUW]] -// CHECK-NOERRNO: declare float @erfcf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @erfcl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @exp(double) [[NUW]] -// CHECK-NOERRNO: declare float @expf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @expl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @exp2(double) [[NUW]] -// CHECK-NOERRNO: declare float @exp2f(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @exp2l(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @expm1(double) [[NUW]] -// CHECK-NOERRNO: declare float @expm1f(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @expm1l(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @fdim(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @fdimf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @floor(double) [[NUW]] -// CHECK-NOERRNO: declare float @floorf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @floorl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @fma(double, double, double) [[NUW]] -// CHECK-NOERRNO: declare float @fmaf(float, float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @fmal(x86_fp80, x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @fmax(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @fmaxf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @fmin(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @fminf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @hypot(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @hypotf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare i32 @ilogb(double) [[NUW]] -// CHECK-NOERRNO: declare i32 @ilogbf(float) [[NUW]] -// CHECK-NOERRNO: declare i32 @ilogbl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare double @atan2(double, double) [[NUWRN:#[0-9]+]] +// CHECK-NOERRNO: declare float @atan2f(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare i32 @abs(i32) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @labs(i64) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @llabs(i64) [[NUWRN]] +// CHECK-NOERRNO: declare double @copysign(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @copysignf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @fabs(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @fabsf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @fabsl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @fmod(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @fmodf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @ldexp(double, i32) [[NUWRN]] +// CHECK-NOERRNO: declare float @ldexpf(float, i32) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NUWRN]] +// CHECK-NOERRNO: declare double @nan(i8*) [[NUWRO:#[0-9]+]] +// CHECK-NOERRNO: declare float @nanf(i8*) [[NUWRO]] +// CHECK-NOERRNO: declare x86_fp80 @nanl(i8*) [[NUWRO]] +// CHECK-NOERRNO: declare double @pow(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @powf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @acos(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @acosf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @acosl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @acosh(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @acoshf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @acoshl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @asin(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @asinf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @asinl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @asinh(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @asinhf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @asinhl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @atan(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @atanf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @atanl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @atanh(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @atanhf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @atanhl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @cbrt(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @cbrtf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @ceil(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @ceilf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @ceill(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @cos(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @cosf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @cosl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @cosh(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @coshf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @coshl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @erf(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @erff(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @erfl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @erfc(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @erfcf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @erfcl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @exp(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @expf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @expl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @exp2(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @exp2f(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @exp2l(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @expm1(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @expm1f(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @expm1l(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @fdim(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @fdimf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @floor(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @floorf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @floorl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @fma(double, double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @fmaf(float, float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @fmal(x86_fp80, x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @fmax(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @fmaxf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @fmin(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @fminf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @hypot(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @hypotf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare i32 @ilogb(double) [[NUWRN]] +// CHECK-NOERRNO: declare i32 @ilogbf(float) [[NUWRN]] +// CHECK-NOERRNO: declare i32 @ilogbl(x86_fp80) [[NUWRN]] // CHECK-NOERRNO: declare double @lgamma(double) [[NONCONST:#[0-9]+]] // CHECK-NOERRNO: declare float @lgammaf(float) [[NONCONST]] // CHECK-NOERRNO: declare x86_fp80 @lgammal(x86_fp80) [[NONCONST]] -// CHECK-NOERRNO: declare i64 @llrint(double) [[NUW]] -// CHECK-NOERRNO: declare i64 @llrintf(float) [[NUW]] -// CHECK-NOERRNO: declare i64 @llrintl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare i64 @llround(double) [[NUW]] -// CHECK-NOERRNO: declare i64 @llroundf(float) [[NUW]] -// CHECK-NOERRNO: declare i64 @llroundl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @log(double) [[NUW]] -// CHECK-NOERRNO: declare float @logf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @logl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @log10(double) [[NUW]] -// CHECK-NOERRNO: declare float @log10f(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @log10l(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @log1p(double) [[NUW]] -// CHECK-NOERRNO: declare float @log1pf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @log1pl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @log2(double) [[NUW]] -// CHECK-NOERRNO: declare float @log2f(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @log2l(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @logb(double) [[NUW]] -// CHECK-NOERRNO: declare float @logbf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @logbl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare i64 @lrint(double) [[NUW]] -// CHECK-NOERRNO: declare i64 @lrintf(float) [[NUW]] -// CHECK-NOERRNO: declare i64 @lrintl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare i64 @lround(double) [[NUW]] -// CHECK-NOERRNO: declare i64 @lroundf(float) [[NUW]] -// CHECK-NOERRNO: declare i64 @lroundl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @nearbyint(double) [[NUW]] -// CHECK-NOERRNO: declare float @nearbyintf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @nextafter(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @nextafterf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @nexttoward(double, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare float @nexttowardf(float, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @remainder(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @remainderf(float, float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @rint(double) [[NUW]] -// CHECK-NOERRNO: declare float @rintf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @rintl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @round(double) [[NUW]] -// CHECK-NOERRNO: declare float @roundf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @roundl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @scalbln(double, i64) [[NUW]] -// CHECK-NOERRNO: declare float @scalblnf(float, i64) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[NUW]] -// CHECK-NOERRNO: declare double @scalbn(double, i32) [[NUW]] -// CHECK-NOERRNO: declare float @scalbnf(float, i32) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[NUW]] -// CHECK-NOERRNO: declare double @sin(double) [[NUW]] -// CHECK-NOERRNO: declare float @sinf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @sinl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @sinh(double) [[NUW]] -// CHECK-NOERRNO: declare float @sinhf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @sinhl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @sqrt(double) [[NUW]] -// CHECK-NOERRNO: declare float @sqrtf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @tan(double) [[NUW]] -// CHECK-NOERRNO: declare float @tanf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @tanl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @tanh(double) [[NUW]] -// CHECK-NOERRNO: declare float @tanhf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @tanhl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @tgamma(double) [[NUW]] -// CHECK-NOERRNO: declare float @tgammaf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @tgammal(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @trunc(double) [[NUW]] -// CHECK-NOERRNO: declare float @truncf(float) [[NUW]] -// CHECK-NOERRNO: declare x86_fp80 @truncl(x86_fp80) [[NUW]] -// CHECK-NOERRNO: declare double @cabs(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @cabsf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @cacos(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @cacosf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @cacosh(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @cacoshf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare double @carg(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @cargf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @casin(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @casinf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @casinh(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @casinhf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @catan(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @catanf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @catanh(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @catanhf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @ccos(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @ccosf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @ccosh(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @ccoshf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @cexp(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @cexpf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare double @cimag(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @cimagf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @conj(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @conjf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @clog(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @clogf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @cproj(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @cprojf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @cpow(double, double, double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[NUW]] -// CHECK-NOERRNO: declare double @creal(double, double) [[NUW]] -// CHECK-NOERRNO: declare float @crealf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @csin(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @csinf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @csinh(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @csinhf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @csqrt(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @csqrtf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @ctan(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @ctanf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare { double, double } @ctanh(double, double) [[NUW]] -// CHECK-NOERRNO: declare <2 x float> @ctanhf(<2 x float>) [[NUW]] -// CHECK-NOERRNO: declare double @__sinpi(double) [[NUW]] -// CHECK-NOERRNO: declare float @__sinpif(float) [[NUW]] -// CHECK-NOERRNO: declare double @__cospi(double) [[NUW]] -// CHECK-NOERRNO: declare float @__cospif(float) [[NUW]] -// CHECK-NOERRNO: declare double @__tanpi(double) [[NUW]] -// CHECK-NOERRNO: declare float @__tanpif(float) [[NUW]] -// CHECK-NOERRNO: declare double @__exp10(double) [[NUW]] -// CHECK-NOERRNO: declare float @__exp10f(float) [[NUW]] +// CHECK-NOERRNO: declare i64 @llrint(double) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @llrintf(float) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @llrintl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @llround(double) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @llroundf(float) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @llroundl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @log(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @logf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @logl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @log10(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @log10f(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @log10l(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @log1p(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @log1pf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @log1pl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @log2(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @log2f(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @log2l(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @logb(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @logbf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @logbl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @lrint(double) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @lrintf(float) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @lrintl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @lround(double) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @lroundf(float) [[NUWRN]] +// CHECK-NOERRNO: declare i64 @lroundl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @nearbyint(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @nearbyintf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @nextafter(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @nextafterf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @nexttoward(double, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare float @nexttowardf(float, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @remainder(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @remainderf(float, float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @rint(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @rintf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @rintl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @round(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @roundf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @roundl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @scalbln(double, i64) [[NUWRN]] +// CHECK-NOERRNO: declare float @scalblnf(float, i64) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[NUWRN]] +// CHECK-NOERRNO: declare double @scalbn(double, i32) [[NUWRN]] +// CHECK-NOERRNO: declare float @scalbnf(float, i32) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[NUWRN]] +// CHECK-NOERRNO: declare double @sin(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @sinf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @sinl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @sinh(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @sinhf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @sinhl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @sqrt(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @sqrtf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @tan(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @tanf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @tanl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @tanh(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @tanhf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @tanhl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @tgamma(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @tgammaf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @tgammal(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @trunc(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @truncf(float) [[NUWRN]] +// CHECK-NOERRNO: declare x86_fp80 @truncl(x86_fp80) [[NUWRN]] +// CHECK-NOERRNO: declare double @cabs(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @cabsf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @cacos(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @cacosf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @cacosh(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @cacoshf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare double @carg(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @cargf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @casin(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @casinf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @casinh(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @casinhf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @catan(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @catanf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @catanh(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @catanhf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @ccos(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @ccosf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @ccosh(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @ccoshf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @cexp(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @cexpf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare double @cimag(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @cimagf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @conj(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @conjf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @clog(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @clogf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @cproj(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @cprojf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @cpow(double, double, double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare double @creal(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare float @crealf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @csin(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @csinf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @csinh(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @csinhf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @csqrt(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @csqrtf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @ctan(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @ctanf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare { double, double } @ctanh(double, double) [[NUWRN]] +// CHECK-NOERRNO: declare <2 x float> @ctanhf(<2 x float>) [[NUWRN]] +// CHECK-NOERRNO: declare double @__sinpi(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @__sinpif(float) [[NUWRN]] +// CHECK-NOERRNO: declare double @__cospi(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @__cospif(float) [[NUWRN]] +// CHECK-NOERRNO: declare double @__tanpi(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @__tanpif(float) [[NUWRN]] +// CHECK-NOERRNO: declare double @__exp10(double) [[NUWRN]] +// CHECK-NOERRNO: declare float @__exp10f(float) [[NUWRN]] -// CHECK-ERRNO: declare i32 @abs(i32) [[NUW:#[0-9]+]] -// CHECK-ERRNO: declare i64 @labs(i64) [[NUW]] -// CHECK-ERRNO: declare i64 @llabs(i64) [[NUW]] -// CHECK-ERRNO: declare double @copysign(double, double) [[NUW]] -// CHECK-ERRNO: declare float @copysignf(float, float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @fabs(double) [[NUW]] -// CHECK-ERRNO: declare float @fabsf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @fabsl(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @nan(i8*) [[NUW]] -// CHECK-ERRNO: declare float @nanf(i8*) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @nanl(i8*) [[NUW]] -// CHECK-ERRNO: declare double @ceil(double) [[NUW]] -// CHECK-ERRNO: declare float @ceilf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @ceill(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @floor(double) [[NUW]] -// CHECK-ERRNO: declare float @floorf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @floorl(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @fmax(double, double) [[NUW]] -// CHECK-ERRNO: declare float @fmaxf(float, float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @fmin(double, double) [[NUW]] -// CHECK-ERRNO: declare float @fminf(float, float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-ERRNO: declare i32 @abs(i32) [[NUWRN:#[0-9]+]] +// CHECK-ERRNO: declare i64 @labs(i64) [[NUWRN]] +// CHECK-ERRNO: declare i64 @llabs(i64) [[NUWRN]] +// CHECK-ERRNO: declare double @copysign(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @copysignf(float, float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @fabs(double) [[NUWRN]] +// CHECK-ERRNO: declare float @fabsf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @fabsl(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @nan(i8*) [[NUWRO:#[0-9]+]] +// CHECK-ERRNO: declare float @nanf(i8*) [[NUWRO]] +// CHECK-ERRNO: declare x86_fp80 @nanl(i8*) [[NUWRO]] +// CHECK-ERRNO: declare double @ceil(double) [[NUWRN]] +// CHECK-ERRNO: declare float @ceilf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @ceill(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @floor(double) [[NUWRN]] +// CHECK-ERRNO: declare float @floorf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @floorl(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @fmax(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @fmaxf(float, float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @fmin(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @fminf(float, float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NUWRN]] // CHECK-ERRNO: declare double @lgamma(double) [[NONCONST:#[0-9]+]] // CHECK-ERRNO: declare float @lgammaf(float) [[NONCONST]] // CHECK-ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[NONCONST]] -// CHECK-ERRNO: declare double @nearbyint(double) [[NUW]] -// CHECK-ERRNO: declare float @nearbyintf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @rint(double) [[NUW]] -// CHECK-ERRNO: declare float @rintf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @rintl(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @round(double) [[NUW]] -// CHECK-ERRNO: declare float @roundf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @roundl(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @trunc(double) [[NUW]] -// CHECK-ERRNO: declare float @truncf(float) [[NUW]] -// CHECK-ERRNO: declare x86_fp80 @truncl(x86_fp80) [[NUW]] -// CHECK-ERRNO: declare double @cabs(double, double) [[NUW]] -// CHECK-ERRNO: declare float @cabsf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @cacos(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @cacosf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @cacosh(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @cacoshf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare double @carg(double, double) [[NUW]] -// CHECK-ERRNO: declare float @cargf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @casin(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @casinf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @casinh(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @casinhf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @catan(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @catanf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @catanh(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @catanhf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @ccos(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @ccosf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @ccosh(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @ccoshf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @cexp(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @cexpf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare double @cimag(double, double) [[NUW]] -// CHECK-ERRNO: declare float @cimagf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @conj(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @conjf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @clog(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @clogf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @cproj(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @cprojf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @cpow(double, double, double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[NUW]] -// CHECK-ERRNO: declare double @creal(double, double) [[NUW]] -// CHECK-ERRNO: declare float @crealf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @csin(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @csinf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @csinh(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @csinhf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @csqrt(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @ctan(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @ctanf(<2 x float>) [[NUW]] -// CHECK-ERRNO: declare { double, double } @ctanh(double, double) [[NUW]] -// CHECK-ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[NUW]] +// CHECK-ERRNO: declare double @nearbyint(double) [[NUWRN]] +// CHECK-ERRNO: declare float @nearbyintf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @rint(double) [[NUWRN]] +// CHECK-ERRNO: declare float @rintf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @rintl(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @round(double) [[NUWRN]] +// CHECK-ERRNO: declare float @roundf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @roundl(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @trunc(double) [[NUWRN]] +// CHECK-ERRNO: declare float @truncf(float) [[NUWRN]] +// CHECK-ERRNO: declare x86_fp80 @truncl(x86_fp80) [[NUWRN]] +// CHECK-ERRNO: declare double @cabs(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @cabsf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @cacos(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @cacosf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @cacosh(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @cacoshf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare double @carg(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @cargf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @casin(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @casinf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @casinh(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @casinhf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @catan(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @catanf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @catanh(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @catanhf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @ccos(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @ccosf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @ccosh(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @ccoshf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @cexp(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @cexpf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare double @cimag(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @cimagf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @conj(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @conjf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @clog(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @clogf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @cproj(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @cprojf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @cpow(double, double, double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare double @creal(double, double) [[NUWRN]] +// CHECK-ERRNO: declare float @crealf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @csin(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @csinf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @csinh(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @csinhf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @csqrt(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @ctan(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @ctanf(<2 x float>) [[NUWRN]] +// CHECK-ERRNO: declare { double, double } @ctanh(double, double) [[NUWRN]] +// CHECK-ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[NUWRN]] -// CHECK-NOERRNO: attributes [[NUW]] = { nounwind readnone{{.*}} } -// CHECK-NOERRNO: attributes [[NONCONST]] = { -// CHECK-NOERRNO-NOT: readnone -// CHECK-NOERRNO-SAME: nounwind{{.*}} } +// CHECK-NOERRNO: attributes [[NUWRN]] = { nounwind readnone{{.*}} } +// CHECK-NOERRNO: attributes [[NUWRO]] = { nounwind readonly{{.*}} } -// CHECK-ERRNO: attributes [[NONCONST]] = { -// CHECK-ERRNO-NOT: readnone -// CHECK-ERRNO-SAME: nounwind{{.*}} } -// CHECK-ERRNO: attributes [[NUW]] = { nounwind readnone{{.*}} } +// CHECK-ERRNO: attributes [[NUWRN]] = { nounwind readnone{{.*}} } +// CHECK-ERRNO: attributes [[NUWRO]] = { nounwind readonly{{.*}} } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/pascal-wchar-string.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/pascal-wchar-string.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/pascal-wchar-string.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/pascal-wchar-string.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s -fpascal-strings -fshort-wchar | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - %s -fpascal-strings -fwchar-type=short -fno-signed-wchar | FileCheck %s // rdar://8020384 #include diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/ppc-vector-compare.cc llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/ppc-vector-compare.cc --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/ppc-vector-compare.cc 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/ppc-vector-compare.cc 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -target-feature +altivec -triple powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: -o - | FileCheck %s + +#include + +// CHECK-LABEL: @_Z5test1Dv8_tS_ +// CHECK: @llvm.ppc.altivec.vcmpequh.p +bool test1(vector unsigned short v1, vector unsigned short v2) { + return v1 == v2; +} + diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/string-literal-short-wstring.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/string-literal-short-wstring.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/string-literal-short-wstring.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/string-literal-short-wstring.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -x c++ -triple %itanium_abi_triple -emit-llvm -fshort-wchar %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM -// RUN: %clang_cc1 -x c++ -triple %ms_abi_triple -emit-llvm -fshort-wchar %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSABI +// RUN: %clang_cc1 -x c++ -triple %itanium_abi_triple -emit-llvm -fwchar-type=short -fno-signed-wchar %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM +// RUN: %clang_cc1 -x c++ -triple %ms_abi_triple -emit-llvm -fwchar-type=short -fno-signed-wchar %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSABI // Runs in c++ mode so that wchar_t is available. // XFAIL: hexagon diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/string-literal-unicode-conversion.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/string-literal-unicode-conversion.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/string-literal-unicode-conversion.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/string-literal-unicode-conversion.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-C %s // RUN: %clang_cc1 -x c++ -std=c++0x -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-CPP0X %s -// RUN: %clang_cc1 -x c++ -std=c++0x -fshort-wchar -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-SHORTWCHAR %s +// RUN: %clang_cc1 -x c++ -std=c++0x -fwchar-type=short -fno-signed-wchar -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-SHORTWCHAR %s // This file contains a mix of ISO-8859-1 and UTF-8 encoded data. // the literal assigned to 'aa' should be the ISO-8859-1 encoding for the code diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/target-builtin-noerror.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/target-builtin-noerror.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/target-builtin-noerror.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/target-builtin-noerror.c 2017-10-17 14:41:55.000000000 +0000 @@ -81,6 +81,7 @@ (void)__builtin_cpu_is("amd"); (void)__builtin_cpu_is("amdfam10h"); (void)__builtin_cpu_is("amdfam15h"); + (void)__builtin_cpu_is("amdfam17h"); (void)__builtin_cpu_is("atom"); (void)__builtin_cpu_is("barcelona"); (void)__builtin_cpu_is("bdver1"); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/tbaa-cast.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/tbaa-cast.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/tbaa-cast.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/tbaa-cast.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \ +// RUN: -emit-llvm -o - | FileCheck %s +// +// Check that we generate correct TBAA information for lvalues constructed +// with use of casts. + +struct V { + unsigned n; +}; + +struct S { + char bytes[4]; +}; + +void foo(S *p) { +// CHECK-LABEL: _Z3fooP1S +// CHECK: store i32 5, {{.*}}, !tbaa [[TAG_V_n:!.*]] + ((V*)p->bytes)->n = 5; +} + +// CHECK-DAG: [[TAG_V_n]] = !{[[TYPE_V:!.*]], [[TYPE_int:!.*]], i64 0} +// CHECK-DAG: [[TYPE_V]] = !{!"_ZTS1V", !{{.*}}, i64 0} +// CHECK-DAG: [[TYPE_int]] = !{!"int", !{{.*}}, i64 0} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/tbaa-for-vptr.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/tbaa-for-vptr.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/tbaa-for-vptr.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/tbaa-for-vptr.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -23,12 +23,12 @@ } // CHECK-LABEL: @_Z7CallFoo -// CHECK: %{{.*}} = load {{.*}} !tbaa ![[NUM:[0-9]+]] +// CHECK: %{{.*}} = load i32 (%struct.A*)**, {{.*}} !tbaa ![[NUM:[0-9]+]] // CHECK: br i1 -// CHECK: load {{.*}}, !tbaa ![[NUM]] +// CHECK: load i8*, {{.*}}, !tbaa ![[NUM]] // // CHECK-LABEL: @_ZN1AC2Ev -// CHECK: store {{.*}} !tbaa ![[NUM]] +// CHECK: store i32 (...)** {{.*}}, !tbaa ![[NUM]] // // CHECK: [[NUM]] = !{[[TYPE:!.*]], [[TYPE]], i64 0} // CHECK: [[TYPE]] = !{!"vtable pointer", !{{.*}} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/wchar-size.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/wchar-size.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGen/wchar-size.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGen/wchar-size.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=LONG-WCHAR // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=SHORT-WCHAR -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - -fshort-wchar %s | FileCheck %s -check-prefix=SHORT-WCHAR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - -fwchar-type=short -fno-signed-wchar %s | FileCheck %s -check-prefix=SHORT-WCHAR // Note: -fno-short-wchar implies the target default is used; so there is no // need to test this separately here. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/catch-undef-behavior.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/catch-undef-behavior.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/catch-undef-behavior.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/catch-undef-behavior.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -426,6 +426,66 @@ p(42); } +namespace FunctionSanitizerVirtualCalls { +struct A { + virtual void f() {} + virtual void g() {} + void h() {} +}; + +struct B : virtual A { + virtual void b() {} + virtual void f(); + void g() final {} + static void q() {} +}; + +void B::f() {} + +void force_irgen() { + A a; + a.g(); + a.h(); + + B b; + b.f(); + b.b(); + b.g(); + B::q(); +} + +// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls1B1fEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv() +// CHECK: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv +// CHECK: prologue + +} + namespace UpcastPointerTest { struct S {}; struct T : S { double d; }; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,161 @@ +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-windows -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-MSABI + +namespace std { + using size_t = decltype(sizeof(0)); + enum class align_val_t : size_t; + struct destroying_delete_t {}; +} + +struct A { + void *data; + ~A(); + void operator delete(A*, std::destroying_delete_t); +}; +void delete_A(A *a) { delete a; } +// CHECK-LABEL: define {{.*}}delete_A +// CHECK: %[[a:.*]] = load +// CHECK: icmp eq %{{.*}} %[[a]], null +// CHECK: br i1 +// +// Ensure that we call the destroying delete and not the destructor. +// CHECK-NOT: call +// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) +// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-NOT: call +// CHECK: } + +struct B { + virtual ~B(); + void operator delete(B*, std::destroying_delete_t); +}; +void delete_B(B *b) { delete b; } +// CHECK-LABEL: define {{.*}}delete_B +// CHECK: %[[b:.*]] = load +// CHECK: icmp eq %{{.*}} %[[b]], null +// CHECK: br i1 +// +// Ensure that we call the virtual destructor and not the operator delete. +// CHECK-NOT: call +// CHECK: %[[VTABLE:.*]] = load +// CHECK: %[[DTOR:.*]] = load +// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[b]] +// CHECK-MSABI-SAME: , i32 1) +// CHECK-NOT: call +// CHECK: } + +struct Padding { + virtual void f(); +}; + +struct C : Padding, A {}; +void delete_C(C *c) { delete c; } +// Check that we perform a derived-to-base conversion on the parameter to 'operator delete'. +// CHECK-LABEL: define {{.*}}delete_C +// CHECK: %[[c:.*]] = load +// CHECK: icmp eq %{{.*}} %[[c]], null +// CHECK: br i1 +// +// CHECK: %[[base:.*]] = getelementptr {{.*}}, i64 8 +// CHECK: %[[castbase:.*]] = bitcast {{.*}} %[[base]] +// +// CHECK: %[[a:.*]] = phi {{.*}} %[[castbase]] +// CHECK: icmp eq %{{.*}} %[[a]], null +// CHECK: br i1 +// +// CHECK-NOT: call +// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) +// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-NOT: call +// CHECK: } + +struct VDel { virtual ~VDel(); }; +struct D : Padding, VDel, B {}; +void delete_D(D *d) { delete d; } +// CHECK-LABEL: define {{.*}}delete_D +// CHECK: %[[d:.*]] = load +// CHECK: icmp eq %{{.*}} %[[d]], null +// CHECK: br i1 +// +// CHECK-NOT: call +// CHECK: %[[VTABLE:.*]] = load +// CHECK: %[[DTOR:.*]] = load +// +// For MS, we don't add a new vtable slot to the primary vtable for the virtual +// destructor. Instead we cast to the VDel base class. +// CHECK-MSABI: bitcast {{.*}} %[[d]] +// CHECK-MSABI-NEXT: getelementptr {{.*}}, i64 8 +// CHECK-MSABI-NEXT: %[[d:.*]] = bitcast i8* +// +// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[d]] +// CHECK-MSABI-SAME: , i32 1) +// CHECK-NOT: call +// CHECK: } + +struct E { void *data; }; +struct F { void operator delete(F *, std::destroying_delete_t, std::size_t, std::align_val_t); void *data; }; +struct alignas(16) G : E, F { void *data; }; + +void delete_G(G *g) { delete g; } +// CHECK-LABEL: define {{.*}}delete_G +// CHECK-NOT: call +// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16) +// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16) +// CHECK-NOT: call +// CHECK: } + +void call_in_dtor(); + +struct H : G { virtual ~H(); } h; +H::~H() { call_in_dtor(); } +// CHECK-ITANIUM-LABEL: define void @_ZN1HD0Ev( +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: getelementptr {{.*}}, i64 24 +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t({{.*}}, i64 48, i64 16) +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: } + +// CHECK-MSABI: define {{.*}} @"\01??_GH@@UEAAPEAXI@Z"( +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: load i32 +// CHECK-MSABI: icmp eq i32 {{.*}}, 0 +// CHECK-MSABI: br i1 +// +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: getelementptr {{.*}}, i64 24 +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) +// CHECK-MSABI: br label %[[RETURN:.*]] +// +// CHECK-MSABI: call void @"\01??_DH@@QEAAXXZ"( +// CHECK-MSABI: br label %[[RETURN]] +// +// CHECK-MSABI: } + +struct I : H { virtual ~I(); alignas(32) char buffer[32]; } i; +I::~I() { call_in_dtor(); } +// CHECK-ITANIUM-LABEL: define void @_ZN1ID0Ev( +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: getelementptr {{.*}}, i64 24 +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t({{.*}}, i64 96, i64 32) +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: } + +// CHECK-MSABI: define {{.*}} @"\01??_GI@@UEAAPEAXI@Z"( +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: load i32 +// CHECK-MSABI: icmp eq i32 {{.*}}, 0 +// CHECK-MSABI: br i1 +// +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: getelementptr {{.*}}, i64 24 +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) +// CHECK-MSABI: br label %[[RETURN:.*]] +// +// CHECK-MSABI: call void @"\01??_DI@@QEAAXXZ"( +// CHECK-MSABI: br label %[[RETURN]] +// +// CHECK-MSABI: } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/dllexport.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/dllexport.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/dllexport.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/dllexport.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -831,6 +831,21 @@ template struct __declspec(dllexport) __declspec(dllimport) ExplicitInstantiationTwoAttributes; // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ" +namespace pr34849 { +// Specializations of exported class template member functions get exported. +template struct __declspec(dllexport) ExportedClassTemplate { void foo(); }; +template<> void ExportedClassTemplate::foo() {} +template struct ExportedClassTemplate; +// M32-DAG: define dllexport x86_thiscallcc void @"\01?foo@?$ExportedClassTemplate@H@pr34849@@QAEXXZ" + +// Specializations of exported class member template functions do not get exported. +struct __declspec(dllexport) ExportedClass { template void bar() ; }; +template<> void ExportedClass::bar() {} +// M32-DAG: define x86_thiscallcc void @"\01??$bar@H@ExportedClass@pr34849@@QAEXXZ" +template struct __declspec(dllexport) ExportedClassTemplate2 { template void baz(); }; +template<> template<> void ExportedClassTemplate2::baz() {} +// M32-DAG: define x86_thiscallcc void @"\01??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ" +} //===----------------------------------------------------------------------===// // Classes with template base classes diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -mconstructor-aliases %s -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s + +// FIXME: We should really consider removing -mconstructor-aliases for MS C++ +// ABI. The risk of bugs introducing ABI incompatibility under +// -mno-constructor-aliases is too high. + +// PR32990 + +// Introduces the virtual destructor. We should use the base destructor +// directly, no thunk needed. +struct __declspec(dllimport) ImportIntroVDtor { + virtual ~ImportIntroVDtor() {} +}; + +struct BaseClass { + virtual ~BaseClass() {} +}; + +// Non-virtually inherits from a non-dllimport base class. We should again call +// the derived base constructor directly. No need for the complete (aka vbase) +// destructor. +struct __declspec(dllimport) ImportOverrideVDtor : public BaseClass { + virtual ~ImportOverrideVDtor() {} +}; + +// Virtually inherits from a non-dllimport base class. This time we need to call +// the complete destructor and emit it inline. It's not exported from the DLL, +// and it must be emitted. +struct __declspec(dllimport) ImportVBaseOverrideVDtor + : public virtual BaseClass { + virtual ~ImportVBaseOverrideVDtor() {} +}; + +extern "C" void testit() { + ImportIntroVDtor t1; + ImportOverrideVDtor t2; + ImportVBaseOverrideVDtor t3; +} + +// The destructors are called in reverse order of construction. Only the third +// needs the complete destructor (_D). +// CHECK-LABEL: define void @testit() +// CHECK: call void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ"(%struct.ImportVBaseOverrideVDtor* %{{.*}}) +// CHECK: call void @"\01??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}}) +// CHECK: call void @"\01??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}}) + +// CHECK-LABEL: define linkonce_odr void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ" +// CHECK-LABEL: declare dllimport void @"\01??1ImportOverrideVDtor@@UEAA@XZ" +// CHECK-LABEL: declare dllimport void @"\01??1ImportIntroVDtor@@UEAA@XZ" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/exceptions-seh.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/exceptions-seh.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/exceptions-seh.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/exceptions-seh.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -76,6 +76,27 @@ // CHECK: [[cont]] // CHECK: br label %[[ret]] +extern "C" void nested_finally() { + __try { + might_throw(); + } __finally { + __try { + might_throw(); + } __finally { + } + } +} + +// CHECK-LABEL: define void @nested_finally() #{{[0-9]+}} +// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: invoke void @might_throw() +// CHECK: call void @"\01?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}}) + +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested_finally@@" +// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: invoke void @might_throw() +// CHECK: call void @"\01?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}}) + void use_seh_in_lambda() { ([]() { __try { diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/finegrain-bitfield-access.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/finegrain-bitfield-access.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenCXX/finegrain-bitfield-access.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenCXX/finegrain-bitfield-access.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,162 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \ +// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \ +// RUN: -emit-llvm -fsanitize=address -o - %s | FileCheck %s --check-prefix=SANITIZE +// Check -fsplit-bitfields will be ignored since sanitizer is enabled. + +struct S1 { + unsigned f1:2; + unsigned f2:6; + unsigned f3:8; + unsigned f4:4; + unsigned f5:8; +}; + +S1 a1; +unsigned read8_1() { + // CHECK-LABEL: @_Z7read8_1v + // CHECK: %bf.load = load i8, i8* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 1), align 1 + // CHECK-NEXT: %bf.cast = zext i8 %bf.load to i32 + // CHECK-NEXT: ret i32 %bf.cast + // SANITIZE-LABEL: @_Z7read8_1v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE: %bf.lshr = lshr i32 %bf.load, 8 + // SANITIZE: %bf.clear = and i32 %bf.lshr, 255 + // SANITIZE: ret i32 %bf.clear + return a1.f3; +} +void write8_1() { + // CHECK-LABEL: @_Z8write8_1v + // CHECK: store i8 3, i8* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 1), align 1 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z8write8_1v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -65281 + // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 768 + // SANITIZE-NEXT: store i32 %bf.set, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: ret void + a1.f3 = 3; +} + +unsigned read8_2() { + // CHECK-LABEL: @_Z7read8_2v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 + // CHECK-NEXT: %bf.lshr = lshr i16 %bf.load, 4 + // CHECK-NEXT: %bf.clear = and i16 %bf.lshr, 255 + // CHECK-NEXT: %bf.cast = zext i16 %bf.clear to i32 + // CHECK-NEXT: ret i32 %bf.cast + // SANITIZE-LABEL: @_Z7read8_2v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: %bf.lshr = lshr i32 %bf.load, 20 + // SANITIZE-NEXT: %bf.clear = and i32 %bf.lshr, 255 + // SANITIZE-NEXT: ret i32 %bf.clear + return a1.f5; +} +void write8_2() { + // CHECK-LABEL: @_Z8write8_2v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 + // CHECK-NEXT: %bf.clear = and i16 %bf.load, -4081 + // CHECK-NEXT: %bf.set = or i16 %bf.clear, 48 + // CHECK-NEXT: store i16 %bf.set, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z8write8_2v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -267386881 + // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 3145728 + // SANITIZE-NEXT: store i32 %bf.set, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: ret void + a1.f5 = 3; +} + +struct S2 { + unsigned long f1:16; + unsigned long f2:16; + unsigned long f3:6; +}; + +S2 a2; +unsigned read16_1() { + // CHECK-LABEL: @_Z8read16_1v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 0), align 8 + // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64 + // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 + // CHECK-NEXT: ret i32 %conv + // SANITIZE-LABEL: @_Z8read16_1v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 65535 + // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32 + // SANITIZE-NEXT: ret i32 %conv + return a2.f1; +} +unsigned read16_2() { + // CHECK-LABEL: @_Z8read16_2v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 1), align 2 + // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64 + // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 + // CHECK-NEXT: ret i32 %conv + // SANITIZE-LABEL: @_Z8read16_2v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 16 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.lshr, 65535 + // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32 + // SANITIZE-NEXT: ret i32 %conv + return a2.f2; +} + +void write16_1() { + // CHECK-LABEL: @_Z9write16_1v + // CHECK: store i16 5, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 0), align 8 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z9write16_1v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -65536 + // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 5 + // SANITIZE-NEXT: store i64 %bf.set, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: ret void + a2.f1 = 5; +} +void write16_2() { + // CHECK-LABEL: @_Z9write16_2v + // CHECK: store i16 5, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 1), align 2 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z9write16_2v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -4294901761 + // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 327680 + // SANITIZE-NEXT: store i64 %bf.set, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: ret void + a2.f2 = 5; +} + +struct S3 { + unsigned long f1:14; + unsigned long f2:18; + unsigned long f3:32; +}; + +S3 a3; +unsigned read32_1() { + // CHECK-LABEL: @_Z8read32_1v + // CHECK: %bf.load = load i32, i32* getelementptr inbounds (%struct.S3, %struct.S3* @a3, i32 0, i32 1), align 4 + // CHECK-NEXT: %bf.cast = zext i32 %bf.load to i64 + // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 + // CHECK-NEXT: ret i32 %conv + // SANITIZE-LABEL: @_Z8read32_1v + // SANITIZE: %bf.load = load i64, i64* getelementptr inbounds {{.*}}, align 8 + // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 32 + // SANITIZE-NEXT: %conv = trunc i64 %bf.lshr to i32 + // SANITIZE-NEXT: ret i32 %conv + return a3.f3; +} +void write32_1() { + // CHECK-LABEL: @_Z9write32_1v + // CHECK: store i32 5, i32* getelementptr inbounds (%struct.S3, %struct.S3* @a3, i32 0, i32 1), align 4 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z9write32_1v + // SANITIZE: %bf.load = load i64, i64* getelementptr inbounds {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 4294967295 + // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 21474836480 + // SANITIZE-NEXT: store i64 %bf.set, i64* getelementptr inbounds {{.*}}, align 8 + // SANITIZE-NEXT: ret void + a3.f3 = 5; +} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenObjC/arc-bridged-cast.m llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenObjC/arc-bridged-cast.m --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenObjC/arc-bridged-cast.m 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenObjC/arc-bridged-cast.m 2017-10-17 14:41:55.000000000 +0000 @@ -102,5 +102,6 @@ // CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue( // CHECK-NOT: call void @objc_release( CFStringRef r = (__bridge CFStringRef)(CreateNSString()); + r = (__bridge CFStringRef)((NSString *)(CreateNSString())); return r; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenObjC/os_log.m llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenObjC/os_log.m --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenObjC/os_log.m 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenObjC/os_log.m 2017-10-17 14:41:55.000000000 +0000 @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O0 | FileCheck %s -check-prefix=CHECK-O0 // Make sure we emit clang.arc.use before calling objc_release as part of the // cleanup. This way we make sure the object will not be released until the @@ -12,28 +13,67 @@ // Behavior of __builtin_os_log differs between platforms, so only test on X86 #ifdef __x86_64__ // CHECK-LABEL: define i8* @test_builtin_os_log +// CHECK-O0-LABEL: define i8* @test_builtin_os_log +// CHECK: (i8* returned %[[BUF:.*]]) +// CHECK-O0: (i8* %[[BUF:.*]]) void *test_builtin_os_log(void *buf) { return __builtin_os_log_format(buf, "capabilities: %@", GenString()); - // CHECK: store i8 2, i8* - // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* {{.*}}, i64 1 - // CHECK: store i8 1, i8* [[NUM_ARGS]] - // - // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* {{.*}}, i64 2 - // CHECK: store i8 64, i8* [[ARG1_DESC]] - // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* {{.*}}, i64 3 - // CHECK: store i8 8, i8* [[ARG1_SIZE]] - // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* {{.*}}, i64 4 - // CHECK: [[ARG1_CAST:%.*]] = bitcast i8* [[ARG1]] to - - // CHECK: [[STRING:%.*]] = {{.*}} call {{.*}} @GenString() - // CHECK: [[STRING_CAST:%.*]] = bitcast {{.*}} [[STRING]] to - // CHECK: call {{.*}} @objc_retainAutoreleasedReturnValue(i8* [[STRING_CAST]]) - // CHECK: store {{.*}} [[STRING]], {{.*}} [[ARG1_CAST]] - - // CHECK: call void (...) @clang.arc.use({{.*}} [[STRING]]) - // CHECK: call void @objc_release(i8* [[STRING_CAST]]) - // CHECK: ret i8* + // CHECK: %[[CALL:.*]] = tail call %[[TY0:.*]]* (...) @GenString() + // CHECK: %[[V0:.*]] = bitcast %[[TY0]]* %[[CALL]] to i8* + // CHECK: %[[V1:.*]] = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %[[V0]]) + // CHECK: %[[V2:.*]] = ptrtoint %[[TY0]]* %[[CALL]] to i64 + // CHECK: store i8 2, i8* %[[BUF]], align 1 + // CHECK: %[[NUMARGS_I:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 + // CHECK: store i8 1, i8* %[[NUMARGS_I]], align 1 + // CHECK: %[[ARGDESCRIPTOR_I:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 + // CHECK: store i8 64, i8* %[[ARGDESCRIPTOR_I]], align 1 + // CHECK: %[[ARGSIZE_I:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 + // CHECK: store i8 8, i8* %[[ARGSIZE_I]], align 1 + // CHECK: %[[ARGDATA_I:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 + // CHECK: %[[ARGDATACAST_I:.*]] = bitcast i8* %[[ARGDATA_I]] to i64* + // CHECK: store i64 %[[V2]], i64* %[[ARGDATACAST_I]], align 1 + // CHECK: tail call void (...) @clang.arc.use(%[[TY0]]* %[[CALL]]) + // CHECK: tail call void @objc_release(i8* %[[V0]]) + // CHECK: ret i8* %[[BUF]] + + // clang.arc.use is used and removed in IR optimizations. At O0, we should not + // emit clang.arc.use, since it will not be removed and we will have a link + // error. + // CHECK-O0: %[[BUF_ADDR:.*]] = alloca i8*, align 8 + // CHECK-O0: store i8* %[[BUF]], i8** %[[BUF_ADDR]], align 8 + // CHECK-O0: %[[V0:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8 + // CHECK-O0: %[[CALL:.*]] = call %[[TY0:.*]]* (...) @GenString() + // CHECK-O0: %[[V1:.*]] = bitcast %[[TY0]]* %[[CALL]] to i8* + // CHECK-O0: %[[V2:.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* %[[V1]]) + // CHECK-O0: %[[V3:.*]] = bitcast i8* %[[V2]] to %[[TY0]]* + // CHECK-O0: %[[V4:.*]] = ptrtoint %[[TY0]]* %[[V3]] to i64 + // CHECK-O0: call void @__os_log_helper_1_2_1_8_64(i8* %[[V0]], i64 %[[V4]]) + // CHECK-O0: %[[V5:.*]] = bitcast %[[TY0]]* %[[V3]] to i8* + // CHECK-O0-NOT call void (...) @clang.arc.use({{.*}} + // CHECK-O0: call void @objc_release(i8* %[[V5]]) + // CHECK-O0: ret i8* %[[V0]] } +// CHECK-O0-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_1_8_64 +// CHECK-O0: (i8* %[[BUFFER:.*]], i64 %[[ARG0:.*]]) + +// CHECK-O0: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 +// CHECK-O0: %[[ARG0_ADDR:.*]] = alloca i64, align 8 +// CHECK-O0: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 +// CHECK-O0: store i64 %[[ARG0]], i64* %[[ARG0_ADDR]], align 8 +// CHECK-O0: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 +// CHECK-O0: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 +// CHECK-O0: store i8 2, i8* %[[SUMMARY]], align 1 +// CHECK-O0: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 +// CHECK-O0: store i8 1, i8* %[[NUMARGS]], align 1 +// CHECK-O0: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 +// CHECK-O0: store i8 64, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK-O0: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 +// CHECK-O0: store i8 8, i8* %[[ARGSIZE]], align 1 +// CHECK-O0: %[[ARGDATA:.*]] = getelementptr i8, i8* %[[BUF]], i64 4 +// CHECK-O0: %[[ARGDATACAST:.*]] = bitcast i8* %[[ARGDATA]] to i64* +// CHECK-O0: %[[V0:.*]] = load i64, i64* %[[ARG0_ADDR]], align 8 +// CHECK-O0: store i64 %[[V0]], i64* %[[ARGDATACAST]], align 1 + #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/address-spaces.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/address-spaces.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/address-spaces.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/address-spaces.cl 2017-10-17 14:41:55.000000000 +0000 @@ -7,6 +7,24 @@ // RUN: %clang_cc1 %s -O0 -triple amdgcn-mesa-mesa3d -emit-llvm -o - | FileCheck --check-prefixes=CHECK,SPIR %s // RUN: %clang_cc1 %s -O0 -triple r600-- -emit-llvm -o - | FileCheck --check-prefixes=CHECK,SPIR %s +// SPIR: %struct.S = type { i32, i32, i32* } +// CL20SPIR: %struct.S = type { i32, i32, i32 addrspace(4)* } +struct S { + int x; + int y; + int *z; +}; + +// CL20-DAG: @g_extern_var = external addrspace(1) global float +// CL20-DAG: @l_extern_var = external addrspace(1) global float +// CL20-DAG: @test_static.l_static_var = internal addrspace(1) global float 0.000000e+00 +// CL20-DAG: @g_static_var = internal addrspace(1) global float 0.000000e+00 + +#ifdef CL20 +// CL20-DAG: @g_s = common addrspace(1) global %struct.S zeroinitializer +struct S g_s; +#endif + // SPIR: i32* %arg // GIZ: i32 addrspace(5)* %arg void f__p(__private int *arg) {} @@ -58,3 +76,53 @@ // CL20-DAG: @f.ii = internal addrspace(1) global i32 0 #endif } + +typedef int int_td; +typedef int *intp_td; +// SPIR: define void @test_typedef(i32 addrspace(1)* %x, i32 addrspace(2)* %y, i32* %z) +void test_typedef(global int_td *x, constant int_td *y, intp_td z) { + *x = *y; + *z = 0; +} + +// SPIR: define void @test_struct() +void test_struct() { + // SPIR: %ps = alloca %struct.S* + // CL20SPIR: %ps = alloca %struct.S addrspace(4)* + struct S *ps; + // SPIR: store i32 0, i32* %x + // CL20SPIR: store i32 0, i32 addrspace(4)* %x + ps->x = 0; +#ifdef CL20 + // CL20SPIR: store i32 0, i32 addrspace(1)* getelementptr inbounds (%struct.S, %struct.S addrspace(1)* @g_s, i32 0, i32 0) + g_s.x = 0; +#endif +} + +// SPIR-LABEL: define void @test_void_par() +void test_void_par(void) {} + +// On ppc64 returns signext i32. +// SPIR-LABEL: define{{.*}} i32 @test_func_return_type() +int test_func_return_type(void) { + return 0; +} + +#ifdef CL20 +extern float g_extern_var; + +// CL20-LABEL: define {{.*}}void @test_extern( +kernel void test_extern(global float *buf) { + extern float l_extern_var; + buf[0] += g_extern_var + l_extern_var; +} + +static float g_static_var; + +// CL20-LABEL: define {{.*}}void @test_static( +kernel void test_static(global float *buf) { + static float l_static_var; + buf[0] += g_static_var + l_static_var; +} + +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/address-spaces-mangling.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/address-spaces-mangling.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/address-spaces-mangling.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/address-spaces-mangling.cl 2017-10-17 14:41:55.000000000 +0000 @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=yes -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefix=ASMANG %s -// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefix=NOASMANG %s +// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=yes -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes=ASMANG,ASMAN10 %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=yes -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes=ASMANG,ASMAN20 %s +// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes=NOASMANG,NOASMAN10 %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes=NOASMANG,NOASMAN20 %s // We check that the address spaces are mangled the same in both version of OpenCL // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s @@ -10,15 +12,17 @@ // warnings, but we do want it for comparison purposes. __attribute__((overloadable)) void ff(int *arg) { } -// ASMANG: @_Z2ffPi -// NOASMANG: @_Z2ffPi +// ASMANG10: @_Z2ffPi +// ASMANG20: @_Z2ffPU3AS4i +// NOASMANG10: @_Z2ffPi +// NOASMANG20: @_Z2ffPU9CLgenerici // OCL-20-DAG: @_Z2ffPU3AS4i // OCL-12-DAG: @_Z2ffPi __attribute__((overloadable)) void f(private int *arg) { } // ASMANG: @_Z1fPi -// NOASMANG: @_Z1fPi +// NOASMANG: @_Z1fPU9CLprivatei // OCL-20-DAG: @_Z1fPi // OCL-12-DAG: @_Z1fPi @@ -42,3 +46,11 @@ // NOASMANG: @_Z1fPU10CLconstanti // OCL-20-DAG: @_Z1fPU3AS2i // OCL-12-DAG: @_Z1fPU3AS2i + +#if __OPENCL_C_VERSION__ >= 200 +__attribute__((overloadable)) +void f(generic int *arg) { } +// ASMANG20: @_Z1fPU3AS4i +// NOASMANG20: @_Z1fPU9CLgenerici +// OCL-20-DAG: @_Z1fPU3AS4i +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/amdgpu-attrs.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/amdgpu-attrs.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/amdgpu-attrs.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/amdgpu-attrs.cl 2017-10-17 14:41:55.000000000 +0000 @@ -151,28 +151,28 @@ // CHECK-NOT: "amdgpu-num-sgpr"="0" // CHECK-NOT: "amdgpu-num-vgpr"="0" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128" -// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { noinline nounwind optnone "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { noinline nounwind optnone "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-num-sgpr"="32" -// CHECK-DAG: attributes [[NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128" +// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" +// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s --check-prefix=CHECK + +typedef struct {int a;} ndrange_t; + +// CHECK-LABEL: define amdgpu_kernel void @test +kernel void test(global char *a, char b, global long *c, long d) { + queue_t default_queue; + unsigned flags = 0; + ndrange_t ndrange; + + enqueue_kernel(default_queue, flags, ndrange, + ^(void) { + a[0] = b; + }); + + enqueue_kernel(default_queue, flags, ndrange, + ^(void) { + a[0] = b; + c[0] = d; + }); +} + +// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>) +// CHECK-SAME: #[[ATTR:[0-9]+]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}} +// CHECK: entry: +// CHECK: %1 = alloca <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>, align 8 +// CHECK: store <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>* %1, align 8 +// CHECK: %2 = addrspacecast <{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i8 }>* %1 to i8 addrspace(4)* +// CHECK: call void @__test_block_invoke(i8 addrspace(4)* %2) +// CHECK: ret void +// CHECK:} + +// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8 addrspace(4)*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>) +// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}} + +// CHECK: attributes #[[ATTR]] = { nounwind "enqueued-block" } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/atomic-ops.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/atomic-ops.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/atomic-ops.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/atomic-ops.cl 2017-10-17 14:41:55.000000000 +0000 @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -O0 -o - -triple=amdgcn-amd-amdhsa-opencl | opt -instnamer -S | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -O0 -o - -triple=amdgcn-amd-amdhsa-amdgizcl | opt -instnamer -S | FileCheck %s // Also test serialization of atomic operations here, to avoid duplicating the test. -// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-pch -O0 -o %t -triple=amdgcn-amd-amdhsa-opencl -// RUN: %clang_cc1 %s -cl-std=CL2.0 -include-pch %t -O0 -triple=amdgcn-amd-amdhsa-opencl -emit-llvm -o - | opt -instnamer -S | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-pch -O0 -o %t -triple=amdgcn-amd-amdhsa-amdgizcl +// RUN: %clang_cc1 %s -cl-std=CL2.0 -include-pch %t -O0 -triple=amdgcn-amd-amdhsa-amdgizcl -emit-llvm -o - | opt -instnamer -S | FileCheck %s #ifndef ALREADY_INCLUDED #define ALREADY_INCLUDED @@ -32,22 +32,22 @@ void fi1(atomic_int *i) { // CHECK-LABEL: @fi1 - // CHECK: load atomic i32, i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: load atomic i32, i32* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst int x = __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_work_group); - // CHECK: load atomic i32, i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}} syncscope("agent") seq_cst + // CHECK: load atomic i32, i32* %{{[.0-9A-Z_a-z]+}} syncscope("agent") seq_cst x = __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_device); - // CHECK: load atomic i32, i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}} seq_cst + // CHECK: load atomic i32, i32* %{{[.0-9A-Z_a-z]+}} seq_cst x = __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_all_svm_devices); - // CHECK: load atomic i32, i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}} syncscope("subgroup") seq_cst + // CHECK: load atomic i32, i32* %{{[.0-9A-Z_a-z]+}} syncscope("subgroup") seq_cst x = __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_sub_group); } void fi2(atomic_int *i) { // CHECK-LABEL: @fi2 - // CHECK: store atomic i32 %{{[.0-9A-Z_a-z]+}}, i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: store atomic i32 %{{[.0-9A-Z_a-z]+}}, i32* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst __opencl_atomic_store(i, 1, memory_order_seq_cst, memory_scope_work_group); } @@ -56,7 +56,7 @@ // CHECK: store atomic i32 %{{[.0-9A-Z_a-z]+}}, i32 addrspace(1)* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst __opencl_atomic_store(ig, 1, memory_order_seq_cst, memory_scope_work_group); - // CHECK: store atomic i32 %{{[.0-9A-Z_a-z]+}}, i32* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: store atomic i32 %{{[.0-9A-Z_a-z]+}}, i32 addrspace(5)* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst __opencl_atomic_store(ip, 1, memory_order_seq_cst, memory_scope_work_group); // CHECK: store atomic i32 %{{[.0-9A-Z_a-z]+}}, i32 addrspace(3)* %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst @@ -65,25 +65,25 @@ void fi3(atomic_int *i, atomic_uint *ui) { // CHECK-LABEL: @fi3 - // CHECK: atomicrmw and i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: atomicrmw and i32* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst int x = __opencl_atomic_fetch_and(i, 1, memory_order_seq_cst, memory_scope_work_group); - // CHECK: atomicrmw min i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: atomicrmw min i32* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst x = __opencl_atomic_fetch_min(i, 1, memory_order_seq_cst, memory_scope_work_group); - // CHECK: atomicrmw max i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: atomicrmw max i32* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst x = __opencl_atomic_fetch_max(i, 1, memory_order_seq_cst, memory_scope_work_group); - // CHECK: atomicrmw umin i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: atomicrmw umin i32* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst x = __opencl_atomic_fetch_min(ui, 1, memory_order_seq_cst, memory_scope_work_group); - // CHECK: atomicrmw umax i32 addrspace(4)* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst + // CHECK: atomicrmw umax i32* %{{[.0-9A-Z_a-z]+}}, i32 %{{[.0-9A-Z_a-z]+}} syncscope("workgroup") seq_cst x = __opencl_atomic_fetch_max(ui, 1, memory_order_seq_cst, memory_scope_work_group); } bool fi4(atomic_int *i) { // CHECK-LABEL: @fi4( - // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32 addrspace(4)* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] syncscope("workgroup") acquire acquire + // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] syncscope("workgroup") acquire acquire // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 // CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]] @@ -100,16 +100,16 @@ // CHECK-NEXT: i32 4, label %[[opencl_subgroup:.*]] // CHECK-NEXT: ] // CHECK: [[opencl_workgroup]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("workgroup") seq_cst + // CHECK: load atomic i32, i32* %{{.*}} syncscope("workgroup") seq_cst // CHECK: br label %[[continue:.*]] // CHECK: [[opencl_device]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("agent") seq_cst + // CHECK: load atomic i32, i32* %{{.*}} syncscope("agent") seq_cst // CHECK: br label %[[continue]] // CHECK: [[opencl_allsvmdevices]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} seq_cst + // CHECK: load atomic i32, i32* %{{.*}} seq_cst // CHECK: br label %[[continue]] // CHECK: [[opencl_subgroup]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("subgroup") seq_cst + // CHECK: load atomic i32, i32* %{{.*}} syncscope("subgroup") seq_cst // CHECK: br label %[[continue]] // CHECK: [[continue]]: int x = __opencl_atomic_load(i, memory_order_seq_cst, scope); @@ -141,29 +141,29 @@ // CHECK-NEXT: i32 4, label %[[SEQ_SUB:.*]] // CHECK-NEXT: ] // CHECK: [[MON_WG]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("workgroup") monotonic + // CHECK: load atomic i32, i32* %{{.*}} syncscope("workgroup") monotonic // CHECK: [[MON_DEV]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("agent") monotonic + // CHECK: load atomic i32, i32* %{{.*}} syncscope("agent") monotonic // CHECK: [[MON_ALL]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} monotonic + // CHECK: load atomic i32, i32* %{{.*}} monotonic // CHECK: [[MON_SUB]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("subgroup") monotonic + // CHECK: load atomic i32, i32* %{{.*}} syncscope("subgroup") monotonic // CHECK: [[ACQ_WG]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("workgroup") acquire + // CHECK: load atomic i32, i32* %{{.*}} syncscope("workgroup") acquire // CHECK: [[ACQ_DEV]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("agent") acquire + // CHECK: load atomic i32, i32* %{{.*}} syncscope("agent") acquire // CHECK: [[ACQ_ALL]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} acquire + // CHECK: load atomic i32, i32* %{{.*}} acquire // CHECK: [[ACQ_SUB]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("subgroup") acquire + // CHECK: load atomic i32, i32* %{{.*}} syncscope("subgroup") acquire // CHECK: [[SEQ_WG]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("workgroup") seq_cst + // CHECK: load atomic i32, i32* %{{.*}} syncscope("workgroup") seq_cst // CHECK: [[SEQ_DEV]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("agent") seq_cst + // CHECK: load atomic i32, i32* %{{.*}} syncscope("agent") seq_cst // CHECK: [[SEQ_ALL]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} seq_cst + // CHECK: load atomic i32, i32* %{{.*}} seq_cst // CHECK: [[SEQ_SUB]]: - // CHECK: load atomic i32, i32 addrspace(4)* %{{.*}} syncscope("subgroup") seq_cst + // CHECK: load atomic i32, i32* %{{.*}} syncscope("subgroup") seq_cst int x = __opencl_atomic_load(i, order, scope); } @@ -181,7 +181,7 @@ float ff3(atomic_float *d) { // CHECK-LABEL: @ff3 - // CHECK: atomicrmw xchg i32 addrspace(4)* {{.*}} syncscope("workgroup") seq_cst + // CHECK: atomicrmw xchg i32* {{.*}} syncscope("workgroup") seq_cst return __opencl_atomic_exchange(d, 2, memory_order_seq_cst, memory_scope_work_group); } @@ -198,10 +198,10 @@ // CHECK-LABEL: @failureOrder void failureOrder(atomic_int *ptr, int *ptr2) { - // CHECK: cmpxchg i32 addrspace(4)* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} syncscope("workgroup") acquire monotonic + // CHECK: cmpxchg i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} syncscope("workgroup") acquire monotonic __opencl_atomic_compare_exchange_strong(ptr, ptr2, 43, memory_order_acquire, memory_order_relaxed, memory_scope_work_group); - // CHECK: cmpxchg weak i32 addrspace(4)* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} syncscope("workgroup") seq_cst acquire + // CHECK: cmpxchg weak i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} syncscope("workgroup") seq_cst acquire __opencl_atomic_compare_exchange_weak(ptr, ptr2, 43, memory_order_seq_cst, memory_order_acquire, memory_scope_work_group); } @@ -279,11 +279,11 @@ // CHECK-LABEL: @test_volatile // CHECK: %[[i_addr:.*]] = alloca i32 // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 - // CHECK-NEXT: store i32 addrspace(4)* %i, i32 addrspace(4)** %[[i_addr]] - // CHECK-NEXT: %[[addr:.*]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[i_addr]] - // CHECK-NEXT: %[[res:.*]] = load atomic volatile i32, i32 addrspace(4)* %[[addr]] syncscope("workgroup") seq_cst - // CHECK-NEXT: store i32 %[[res]], i32* %[[atomicdst]] - // CHECK-NEXT: %[[retval:.*]] = load i32, i32* %[[atomicdst]] + // CHECK-NEXT: store i32* %i, i32* addrspace(5)* %[[i_addr]] + // CHECK-NEXT: %[[addr:.*]] = load i32*, i32* addrspace(5)* %[[i_addr]] + // CHECK-NEXT: %[[res:.*]] = load atomic volatile i32, i32* %[[addr]] syncscope("workgroup") seq_cst + // CHECK-NEXT: store i32 %[[res]], i32 addrspace(5)* %[[atomicdst]] + // CHECK-NEXT: %[[retval:.*]] = load i32, i32 addrspace(5)* %[[atomicdst]] // CHECK-NEXT: ret i32 %[[retval]] return __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_work_group); } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/blocks.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/blocks.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/blocks.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/blocks.cl 2017-10-17 14:41:55.000000000 +0000 @@ -1,17 +1,54 @@ -// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefix=GENERIC -check-prefix=COMMON %s -// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa-opencl | FileCheck -check-prefix=AMD -check-prefix=COMMON %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa-opencl | FileCheck -check-prefixes=COMMON,AMD %s -// Checking for null instead of @__NSConcreteGlobalBlock symbol -// COMMON: @__block_literal_global = internal addrspace(1) constant { i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } { i8** null +// COMMON: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } +// SPIR: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 12, i32 4, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) } +// AMD: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 16, i32 8, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) } +// COMMON-NOT: .str + +// COMMON-LABEL: define internal {{.*}}void @block_A_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a) void (^block_A)(local void *) = ^(local void *a) { return; }; +// COMMON-LABEL: define {{.*}}void @foo() void foo(){ int i; -// Checking for null instead of @_NSConcreteStackBlock symbol -// COMMON: store i8* null, i8** %block.isa + // COMMON-NOT: %block.isa + // COMMON-NOT: %block.flags + // COMMON-NOT: %block.reserved + // COMMON-NOT: %block.descriptor + // COMMON: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 0 + // SPIR: store i32 16, i32* %[[block_size]] + // AMD: store i32 20, i32* %[[block_size]] + // COMMON: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 1 + // SPIR: store i32 4, i32* %[[block_align]] + // AMD: store i32 8, i32* %[[block_align]] + // COMMON: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block:.*]], i32 0, i32 2 + // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (i32 (i8 addrspace(4)*)* @__foo_block_invoke to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %[[block_invoke]] + // COMMON: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]], i32 0, i32 3 + // COMMON: %[[i_value:.*]] = load i32, i32* %i + // COMMON: store i32 %[[i_value]], i32* %[[block_captured]], + // COMMON: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]] to i32 ()* + // COMMON: %[[blk_gen_ptr:.*]] = addrspacecast i32 ()* %[[blk_ptr]] to i32 () addrspace(4)* + // COMMON: store i32 () addrspace(4)* %[[blk_gen_ptr]], i32 () addrspace(4)** %[[block_B:.*]], + // COMMON: %[[blk_gen_ptr:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]] + // COMMON: %[[block_literal:.*]] = bitcast i32 () addrspace(4)* %[[blk_gen_ptr]] to %struct.__opencl_block_literal_generic addrspace(4)* + // COMMON: %[[invoke_addr:.*]] = getelementptr inbounds %struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]], i32 0, i32 2 + // COMMON: %[[blk_gen_ptr:.*]] = bitcast %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]] to i8 addrspace(4)* + // COMMON: %[[invoke_func_ptr:.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %[[invoke_addr]] + // COMMON: %[[invoke_func:.*]] = addrspacecast i8 addrspace(4)* %[[invoke_func_ptr]] to i32 (i8 addrspace(4)*)* + // COMMON: call {{.*}}i32 %[[invoke_func]](i8 addrspace(4)* %[[blk_gen_ptr]]) + int (^ block_B)(void) = ^{ return i; }; + block_B(); } + +// COMMON-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor) +// COMMON: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)* +// COMMON: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)* %[[block]], i32 0, i32 3 +// COMMON: %[[block_capture:.*]] = load i32, i32 addrspace(4)* %[[block_capture_addr]] + +// COMMON-NOT: define{{.*}}@__foo_block_invoke_kernel diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/builtins-amdgcn.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/builtins-amdgcn.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 2017-10-17 14:41:55.000000000 +0000 @@ -421,6 +421,25 @@ // CHECK: declare i64 @llvm.read_register.i64(metadata) #[[NOUNWIND_READONLY:[0-9]+]] +// CHECK-LABEL: @test_read_exec_lo( +// CHECK: call i32 @llvm.read_register.i32(metadata ![[EXEC_LO:[0-9]+]]) #[[READ_EXEC_ATTRS]] +void test_read_exec_lo(global uint* out) { + *out = __builtin_amdgcn_read_exec_lo(); +} + +// CHECK-LABEL: @test_read_exec_hi( +// CHECK: call i32 @llvm.read_register.i32(metadata ![[EXEC_HI:[0-9]+]]) #[[READ_EXEC_ATTRS]] +void test_read_exec_hi(global uint* out) { + *out = __builtin_amdgcn_read_exec_hi(); +} + +// CHECK-LABEL: @test_dispatch_ptr +// CHECK: call i8 addrspace(2)* @llvm.amdgcn.dispatch.ptr() +void test_dispatch_ptr(__attribute__((address_space(2))) unsigned char ** out) +{ + *out = __builtin_amdgcn_dispatch_ptr(); +} + // CHECK-LABEL: @test_kernarg_segment_ptr // CHECK: call i8 addrspace(2)* @llvm.amdgcn.kernarg.segment.ptr() void test_kernarg_segment_ptr(__attribute__((address_space(2))) unsigned char ** out) @@ -492,3 +511,5 @@ // CHECK-DAG: attributes #[[NOUNWIND_READONLY:[0-9]+]] = { nounwind readonly } // CHECK-DAG: attributes #[[READ_EXEC_ATTRS]] = { convergent } // CHECK-DAG: ![[EXEC]] = !{!"exec"} +// CHECK-DAG: ![[EXEC_LO]] = !{!"exec_lo"} +// CHECK-DAG: ![[EXEC_HI]] = !{!"exec_hi"} diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl 2017-10-17 14:41:55.000000000 +0000 @@ -6,10 +6,30 @@ typedef void (^bl_t)(local void *); typedef struct {int a;} ndrange_t; -// N.B. The check here only exists to set BL_GLOBAL -// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_GLOBAL:@__block_literal_global(\.[0-9]+)?]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*) +// COMMON: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } + +// For a block global variable, first emit the block literal as a global variable, then emit the block variable itself. +// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INV_G:@[^ ]+]] to i8*) to i8 addrspace(4)*) } +// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*) + +// For anonymous blocks without captures, emit block literals as global variable. +// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*, i8 addrspace(3)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVG8:@[^ ]+]] to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INVG9:@[^ ]+]] to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } +// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) } + +// Emits block literal [[BL_GLOBAL]], invoke function [[INV_G]] and global block variable @block_G +// COMMON: define internal spir_func void [[INV_G]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}}) const bl_t block_G = (bl_t) ^ (local void *a) {}; +// COMMON-LABEL: define spir_kernel void @device_side_enqueue(i32 addrspace(1)* %{{.*}}, i32 addrspace(1)* %b, i32 %i) kernel void device_side_enqueue(global int *a, global int *b, int i) { // COMMON: %default_queue = alloca %opencl.queue_t* queue_t default_queue; @@ -24,61 +44,84 @@ // COMMON: %event_wait_list2 = alloca [1 x %opencl.clk_event_t*] clk_event_t event_wait_list2[] = {clk_event}; + // Emits block literal on stack and block kernel [[INVLK1]]. // COMMON: [[NDR:%[a-z0-9]+]] = alloca %struct.ndrange_t, align 4 // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags - // COMMON: [[BL:%[0-9]+]] = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(2)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block to void ()* + // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL1:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke + // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()* + // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()* // COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)* - // COMMON: call i32 @__enqueue_kernel_basic(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* [[BL_I8]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_basic( + // COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVLK1:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* [[BL_I8]]) enqueue_kernel(default_queue, flags, ndrange, ^(void) { a[i] = b[i]; }); + // Emits block literal on stack and block kernel [[INVLK2]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %event_wait_list to %opencl.clk_event_t{{.*}}* addrspace(4)* // COMMON: [[EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %clk_event to %opencl.clk_event_t{{.*}}* addrspace(4)* - // COMMON: [[BL:%[0-9]+]] = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(2)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()* + // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL2:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke + // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()* // COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)* - // COMMON: call i32 @__enqueue_kernel_basic_events(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], i8 addrspace(4)* [[BL_I8]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_basic_events + // COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVLK2:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* [[BL_I8]]) + enqueue_kernel(default_queue, flags, ndrange, 2, &event_wait_list, &clk_event, ^(void) { a[i] = b[i]; }); + // Emits global block literal [[BLG1]] and block kernel [[INVGK1]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // B32: %[[TMP:.*]] = alloca [1 x i32] // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0 // B32: store i32 256, i32* %[[TMP1]], align 4 - // B32: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [1 x i64] // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 256, i64* %[[TMP1]], align 8 - // B64: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs( + // COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK1:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, ^(local void *p) { return; }, 256); char c; + // Emits global block literal [[BLG2]] and block kernel [[INVGK2]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // B32: %[[TMP:.*]] = alloca [1 x i32] // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0 // B32: store i32 %{{.*}}, i32* %[[TMP1]], align 4 - // B32: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [1 x i64] // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8 - // B64: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs( + // COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK2:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, ^(local void *p) { return; }, c); + // Emits global block literal [[BLG3]] and block kernel [[INVGK3]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // COMMON: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0 @@ -87,17 +130,22 @@ // B32: %[[TMP:.*]] = alloca [1 x i32] // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0 // B32: store i32 256, i32* %[[TMP1]], align 4 - // B32: call i32 @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]], i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [1 x i64] // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 256, i64* %[[TMP1]], align 8 - // B64: call i32 @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]], i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_events_vaargs + // COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]], + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK3:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event, ^(local void *p) { return; }, 256); + // Emits global block literal [[BLG4]] and block kernel [[INVGK4]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // COMMON: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0 @@ -106,11 +154,15 @@ // B32: %[[TMP:.*]] = alloca [1 x i32] // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0 // B32: store i32 %{{.*}}, i32* %[[TMP1]], align 4 - // B32: call i32 @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [1 x i64] // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8 - // B64: call i32 @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_events_vaargs + // COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK4:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event, ^(local void *p) { return; @@ -118,22 +170,28 @@ c); long l; + // Emits global block literal [[BLG5]] and block kernel [[INVGK5]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // B32: %[[TMP:.*]] = alloca [1 x i32] // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0 // B32: store i32 %{{.*}}, i32* %[[TMP1]], align 4 - // B32: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [1 x i64] // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8 - // B64: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs + // COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK5:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, ^(local void *p) { return; }, l); + // Emits global block literal [[BLG6]] and block kernel [[INVGK6]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // B32: %[[TMP:.*]] = alloca [3 x i32] @@ -143,7 +201,6 @@ // B32: store i32 2, i32* %[[TMP2]], align 4 // B32: %[[TMP3:.*]] = getelementptr [3 x i32], [3 x i32]* %[[TMP]], i32 0, i32 2 // B32: store i32 4, i32* %[[TMP3]], align 4 - // B32: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [3 x i64] // B64: %[[TMP1:.*]] = getelementptr [3 x i64], [3 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 1, i64* %[[TMP1]], align 8 @@ -151,52 +208,132 @@ // B64: store i64 2, i64* %[[TMP2]], align 8 // B64: %[[TMP3:.*]] = getelementptr [3 x i64], [3 x i64]* %[[TMP]], i32 0, i32 2 // B64: store i64 4, i64* %[[TMP3]], align 8 - // B64: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs + // COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK6:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, ^(local void *p1, local void *p2, local void *p3) { return; }, 1, 2, 4); + // Emits global block literal [[BLG7]] and block kernel [[INVGK7]]. // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags // B32: %[[TMP:.*]] = alloca [1 x i32] // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0 // B32: store i32 0, i32* %[[TMP1]], align 4 - // B32: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i32* %[[TMP1]]) // B64: %[[TMP:.*]] = alloca [1 x i64] // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0 // B64: store i64 4294967296, i64* %[[TMP1]], align 8 - // B64: call i32 @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{(.[0-9]+)?}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* @__block_literal_global{{(.[0-9]+)?}} to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, i64* %[[TMP1]]) + // COMMON-LABEL: call i32 @__enqueue_kernel_vaargs + // COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK7:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1, + // B32-SAME: i32* %[[TMP1]]) + // B64-SAME: i64* %[[TMP1]]) enqueue_kernel(default_queue, flags, ndrange, ^(local void *p) { return; }, 4294967296L); + // Emits global block literal [[BLG8]] and invoke function [[INVG8]]. // The full type of these expressions are long (and repeated elsewhere), so we // capture it as part of the regex for convenience and clarity. - // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_A:@__block_literal_global(\.[0-9]+)?]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A + // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A void (^const block_A)(void) = ^{ return; }; - // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_B:@__block_literal_global(\.[0-9]+)?]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B + // Emits global block literal [[BLG9]] and invoke function [[INVG9]]. + // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B void (^const block_B)(local void *) = ^(local void *a) { return; }; - // COMMON: call i32 @__get_kernel_work_group_size_impl(i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_A]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + // Uses global block literal [[BLG8]] and invoke function [[INVG8]]. + // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2) + // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)* + // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + block_A(); + + // Emits global block literal [[BLG8]] and block kernel [[INVGK8]]. [[INVGK8]] calls [[INVG8]]. + // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue + // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags + // COMMON-LABEL: call i32 @__enqueue_kernel_basic( + // COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + enqueue_kernel(default_queue, flags, ndrange, block_A); + + // Uses block kernel [[INVGK8]] and global block literal [[BLG8]]. + // COMMON: call i32 @__get_kernel_work_group_size_impl( + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*)) unsigned size = get_kernel_work_group_size(block_A); - // COMMON: call i32 @__get_kernel_work_group_size_impl(i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_B]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + + // Uses global block literal [[BLG8]] and invoke function [[INVG8]]. Make sure no redundant block literal and invoke functions are emitted. + // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2) + // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)* + // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + block_A(); + + // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INV9]]. + // COMMON: call i32 @__get_kernel_work_group_size_impl( + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK9:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*)) size = get_kernel_work_group_size(block_B); - // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_A]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + + // Uses global block literal [[BLG8]] and block kernel [[INVGK8]]. Make sure no redundant block literal ind invoke functions are emitted. + // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl( + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*)) size = get_kernel_preferred_work_group_size_multiple(block_A); - // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*)) + + // Uses global block literal [[BL_GLOBAL]] and block kernel [[INV_G_K]]. [[INV_G_K]] calls [[INV_G]]. + // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl( + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INV_G_K:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*)) size = get_kernel_preferred_work_group_size_multiple(block_G); - // COMMON: call i32 @__get_kernel_max_sub_group_size_for_ndrange_impl(%struct.ndrange_t* {{.*}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* {{.*}} to i8 addrspace(1)*) to i8 addrspace(4)*)) + // Emits global block literal [[BLG10]] and block kernel [[INVGK10]]. + // COMMON: call i32 @__get_kernel_max_sub_group_size_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK10:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*)) size = get_kernel_max_sub_group_size_for_ndrange(ndrange, ^(){}); - // COMMON: call i32 @__get_kernel_sub_group_count_for_ndrange_impl(%struct.ndrange_t* {{.*}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* {{.*}} to i8 addrspace(1)*) to i8 addrspace(4)*)) + + // Emits global block literal [[BLG11]] and block kernel [[INVGK11]]. + // COMMON: call i32 @__get_kernel_sub_group_count_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}}, + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK11:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*), + // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*)) size = get_kernel_sub_group_count_for_ndrange(ndrange, ^(){}); } + +// COMMON: define internal spir_kernel void [[INVLK1]](i8 addrspace(4)*) #{{[0-9]+}} { +// COMMON: entry: +// COMMON: call void @__device_side_enqueue_block_invoke(i8 addrspace(4)* %0) +// COMMON: ret void +// COMMON: } +// COMMON: define internal spir_kernel void [[INVLK2]](i8 addrspace(4)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK1]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK2]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK3]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK4]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK5]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK6]](i8 addrspace(4)*, i8 addrspace(3)*, i8 addrspace(3)*, i8 addrspace(3)*) #{{[0-9]+}} { +// COMMON: entry: +// COMMON: call void @__device_side_enqueue_block_invoke_8(i8 addrspace(4)* %0, i8 addrspace(3)* %1, i8 addrspace(3)* %2, i8 addrspace(3)* %3) +// COMMON: ret void +// COMMON: } +// COMMON: define internal spir_kernel void [[INVGK7]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_func void [[INVG8]](i8 addrspace(4)*{{.*}}) +// COMMON: define internal spir_func void [[INVG9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK8]](i8 addrspace(4)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INV_G_K]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK10]](i8 addrspace(4)*{{.*}}) +// COMMON: define internal spir_kernel void [[INVGK11]](i8 addrspace(4)*{{.*}}) diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/convergent.cl llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/convergent.cl --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CodeGenOpenCL/convergent.cl 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CodeGenOpenCL/convergent.cl 2017-10-17 14:41:55.000000000 +0000 @@ -1,9 +1,19 @@ -// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - | opt -instnamer -S | FileCheck %s +// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - | opt -instnamer -S | FileCheck -enable-var-scope %s + +// This is initially assumed convergent, but can be deduced to not require it. + +// CHECK-LABEL: define spir_func void @non_convfun() local_unnamed_addr #0 +// CHECK: ret void +__attribute__((noinline)) +void non_convfun(void) { + volatile int* p; + *p = 0; +} void convfun(void) __attribute__((convergent)); -void non_convfun(void); void nodupfun(void) __attribute__((noduplicate)); +// External functions should be assumed convergent. void f(void); void g(void); @@ -17,19 +27,23 @@ // non_convfun(); // } // -// CHECK: define spir_func void @test_merge_if(i32 %[[a:.+]]) -// CHECK: %[[tobool:.+]] = icmp eq i32 %[[a]], 0 +// CHECK-LABEL: define spir_func void @test_merge_if(i32 %a) local_unnamed_addr #1 { +// CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0 // CHECK: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]] + // CHECK: [[if_then]]: // CHECK: tail call spir_func void @f() // CHECK: tail call spir_func void @non_convfun() // CHECK: tail call spir_func void @g() + // CHECK: br label %[[if_end3:.+]] + // CHECK: [[if_end3_critedge]]: // CHECK: tail call spir_func void @non_convfun() // CHECK: br label %[[if_end3]] + // CHECK: [[if_end3]]: -// CHECK-LABEL: ret void +// CHECK: ret void void test_merge_if(int a) { if (a) { @@ -41,13 +55,13 @@ } } -// CHECK-DAG: declare spir_func void @f() -// CHECK-DAG: declare spir_func void @non_convfun() -// CHECK-DAG: declare spir_func void @g() +// CHECK-DAG: declare spir_func void @f() local_unnamed_addr #2 +// CHECK-DAG: declare spir_func void @g() local_unnamed_addr #2 + // Test two if's are not merged. -// CHECK: define spir_func void @test_no_merge_if(i32 %[[a:.+]]) -// CHECK: %[[tobool:.+]] = icmp eq i32 %[[a]], 0 +// CHECK-LABEL: define spir_func void @test_no_merge_if(i32 %a) local_unnamed_addr #1 +// CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0 // CHECK: br i1 %[[tobool]], label %[[if_end:.+]], label %[[if_then:.+]] // CHECK: [[if_then]]: // CHECK: tail call spir_func void @f() @@ -56,7 +70,7 @@ // CHECK: br label %[[if_end]] // CHECK: [[if_end]]: // CHECK: %[[tobool_pr:.+]] = phi i1 [ true, %[[if_then]] ], [ false, %{{.+}} ] -// CHECK: tail call spir_func void @convfun() #[[attr5:.+]] +// CHECK: tail call spir_func void @convfun() #[[attr4:.+]] // CHECK: br i1 %[[tobool_pr]], label %[[if_then2:.+]], label %[[if_end3:.+]] // CHECK: [[if_then2]]: // CHECK: tail call spir_func void @g() @@ -74,20 +88,20 @@ } } -// CHECK: declare spir_func void @convfun(){{[^#]*}} #[[attr2:[0-9]+]] +// CHECK: declare spir_func void @convfun(){{[^#]*}} #2 // Test loop is unrolled for convergent function. -// CHECK-LABEL: define spir_func void @test_unroll() -// CHECK: tail call spir_func void @convfun() #[[attr5:[0-9]+]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] -// CHECK: tail call spir_func void @convfun() #[[attr5]] +// CHECK-LABEL: define spir_func void @test_unroll() local_unnamed_addr #1 +// CHECK: tail call spir_func void @convfun() #[[attr4:[0-9]+]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] +// CHECK: tail call spir_func void @convfun() #[[attr4]] // CHECK-LABEL: ret void void test_unroll() { @@ -101,7 +115,7 @@ // CHECK: [[for_cond_cleanup:.+]]: // CHECK: ret void // CHECK: [[for_body]]: -// CHECK: tail call spir_func void @nodupfun() #[[attr6:[0-9]+]] +// CHECK: tail call spir_func void @nodupfun() #[[attr5:[0-9]+]] // CHECK-NOT: call spir_func void @nodupfun() // CHECK: br i1 %{{.+}}, label %[[for_body]], label %[[for_cond_cleanup]] @@ -112,7 +126,9 @@ // CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]] -// CHECK-DAG: attributes #[[attr2]] = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK-DAG: attributes #[[attr3]] = { {{[^}]*}}noduplicate{{[^}]*}} } -// CHECK-DAG: attributes #[[attr5]] = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK-DAG: attributes #[[attr6]] = { {{[^}]*}}noduplicate{{[^}]*}} } +// CHECK: attributes #0 = { noinline norecurse nounwind " +// CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} } +// CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} } +// CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } +// CHECK: attributes #4 = { {{[^}]*}}convergent{{[^}]*}} } +// CHECK: attributes #5 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CoverageMapping/deferred-region.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CoverageMapping/deferred-region.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CoverageMapping/deferred-region.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CoverageMapping/deferred-region.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -31,11 +31,28 @@ // CHECK-LABEL: _Z3mazv: void maz() { if (true) - return; // CHECK: Gap,File 0, [[@LINE]]:11 -> 36:3 = (#0 - #1) + return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1) return; // CHECK-NOT: Gap } +// CHECK-LABEL: _Z4maazv: +void maaz() { + if (true) + return; // CHECK: Gap,File 0, [[@LINE]]:11 + else + return; // CHECK-NOT: Gap,File 0, [[@LINE]] +} + +// CHECK-LABEL: _Z5maaazv: +void maaaz() { + if (true) { + return; + } else { // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 + return; // CHECK-NOT: Gap,File 0, [[@LINE]] + } +} + // CHECK-LABEL: _Z3bari: void bar(int x) { IF (x) @@ -158,6 +175,9 @@ foo(1); fooo(0); fooo(1); + maz(); + maaz(); + maaaz(); baz(); bar(0); bar(1); diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CoverageMapping/logical.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CoverageMapping/logical.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CoverageMapping/logical.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CoverageMapping/logical.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,13 +1,18 @@ // RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name logical.cpp %s | FileCheck %s -int main() { // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+10]]:2 = #0 +int main() { // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+15]]:2 = #0 bool bt = true; bool bf = false; - bool a = bt && bf; // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE]]:20 = #1 - a = bt && + bool a = bt && bf; // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE]]:14 = #0 + // CHECK-NEXT: File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:20 = #1 + + a = bt && // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0 bf; // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #2 - a = bf || bt; // CHECK-NEXT: File 0, [[@LINE]]:13 -> [[@LINE]]:15 = #3 - a = bf || + + a = bf || bt; // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0 + // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE-1]]:15 = #3 + + a = bf || // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0 bt; // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #4 return 0; } diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CoverageMapping/macro-expansion.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/CoverageMapping/macro-expansion.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CoverageMapping/macro-expansion.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CoverageMapping/macro-expansion.c 2017-10-17 14:41:55.000000000 +0000 @@ -23,10 +23,12 @@ // CHECK-NEXT: Expansion,File 4, [[@LINE+2]]:20 -> [[@LINE+2]]:22 = (#0 + #8) // CHECK-NEXT: File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = (#0 + #8) #define M3(x) do { M2(x); } while (0) -// CHECK-NEXT: File 5, [[@LINE+2]]:15 -> [[@LINE+2]]:27 = #0 +// CHECK-NEXT: File 5, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = #0 +// CHECK-NEXT: File 5, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #0 // CHECK-NEXT: File 5, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #12 #define M4(x) ((x) && (x)) -// CHECK-NEXT: File 6, [[@LINE+2]]:15 -> [[@LINE+2]]:27 = #0 +// CHECK-NEXT: File 6, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = #0 +// CHECK-NEXT: File 6, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #0 // CHECK-NEXT: File 6, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #14 #define M5(x) ((x) || (x)) // CHECK-NEXT: File 7, [[@LINE+1]]:15 -> [[@LINE+1]]:26 = #0 diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/conv/conv.prom/p2.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/conv/conv.prom/p2.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/conv/conv.prom/p2.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/conv/conv.prom/p2.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -triple x86_64-pc-linux-gnu -ffreestanding %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -triple x86_64-pc-linux-gnu -ffreestanding -fshort-wchar %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -triple x86_64-pc-linux-gnu -ffreestanding -fwchar-type=short -fno-signed-wchar %s // expected-no-diagnostics #include diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/except/except.spec/p1.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/except/except.spec/p1.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/except/except.spec/p1.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/except/except.spec/p1.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -86,3 +86,12 @@ f<0>(); // expected-note{{in instantiation of function template specialization}} } } + +namespace FuncTmplNoexceptError { + int a = 0; + // expected-error@+1{{argument to noexcept specifier must be a constant expression}} + template T f() noexcept(a++){ return {};} + void g(){ + f(); + } +}; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/global-vs-module.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/global-vs-module.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/global-vs-module.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/global-vs-module.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s +// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s -DEXPORT +// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s -DUSING + +#ifndef NO_GLOBAL +extern int var; // expected-note {{previous declaration is here}} +int func(); // expected-note {{previous declaration is here}} +struct str; // expected-note {{previous declaration is here}} +using type = int; + +template extern int var_tpl; // expected-note {{previous declaration is here}} +template int func_tpl(); // expected-note-re {{{{previous declaration is here|target of using declaration}}}} +template struct str_tpl; // expected-note {{previous declaration is here}} +template using type_tpl = int; // expected-note {{previous declaration is here}} + +typedef int type; +namespace ns { using ::func; } +namespace ns_alias = ns; +#endif + +export module M; + +#ifdef USING +using ::var; +using ::func; +using ::str; +using ::type; +using ::var_tpl; +using ::func_tpl; // expected-note {{using declaration}} +using ::str_tpl; +using ::type_tpl; +#endif + +#ifdef EXPORT +export { +#endif + +extern int var; // expected-error {{declaration of 'var' in module M follows declaration in the global module}} +int func(); // expected-error {{declaration of 'func' in module M follows declaration in the global module}} +struct str; // expected-error {{declaration of 'str' in module M follows declaration in the global module}} +using type = int; + +template extern int var_tpl; // expected-error {{declaration of 'var_tpl' in module M follows declaration in the global module}} +// FIXME: Is this the right diagnostic in the -DUSING case? +template int func_tpl(); // expected-error-re {{{{declaration of 'func_tpl' in module M follows declaration in the global module|conflicts with target of using declaration}}}} +template struct str_tpl; // expected-error {{declaration of 'str_tpl' in module M follows declaration in the global module}} +template using type_tpl = int; // expected-error {{declaration of 'type_tpl' in module M follows declaration in the global module}} + +typedef int type; +namespace ns { using ::func; } +namespace ns_alias = ns; + +#ifdef EXPORT +} +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-global.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-global.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-global.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-global.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,19 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-ts -emit-module-interface -std=c++17 %S/global-vs-module.cpp -o %t -DNO_GLOBAL -DEXPORT +// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s -fmodule-file=%t + +import M; + +extern int var; // expected-error {{declaration of 'var' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:38 {{previous}} +int func(); // expected-error {{declaration of 'func' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:39 {{previous}} +struct str; // expected-error {{declaration of 'str' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:40 {{previous}} +using type = int; + +template extern int var_tpl; // expected-error {{declaration of 'var_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:43 {{previous}} +template int func_tpl(); // expected-error {{declaration of 'func_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:45 {{previous}} +template struct str_tpl; // expected-error {{declaration of 'str_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:46 {{previous}} +template using type_tpl = int; // expected-error {{declaration of 'type_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:47 {{previous}} + +typedef int type; +namespace ns { using ::func; } +namespace ns_alias = ns; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,44 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// +// Some of the following tests intentionally have no -verify in their RUN +// lines; we are testing that those cases do not produce errors. +// +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %S/global-vs-module.cpp -emit-module-interface -o %t/M.pcm -DNO_GLOBAL -DEXPORT +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -DMODULE_INTERFACE -verify +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -DMODULE_INTERFACE -DNO_IMPORT +// +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -emit-module-interface -o %t/N.pcm -DMODULE_INTERFACE -DNO_ERRORS +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -verify +// FIXME: Once we start importing "import" declarations properly, this should +// be rejected (-verify should be added to the following line). +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -DNO_IMPORT +// +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -emit-module-interface -o %t/N-no-M.pcm -DMODULE_INTERFACE -DNO_ERRORS -DNO_IMPORT +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N-no-M.pcm -verify +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N-no-M.pcm -DNO_IMPORT + +#ifdef MODULE_INTERFACE +export +#endif +module N; + +#ifndef NO_IMPORT +import M; +#endif + +#ifndef NO_ERRORS +extern int var; // expected-error {{declaration of 'var' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:38 {{previous}} +int func(); // expected-error {{declaration of 'func' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:39 {{previous}} +struct str; // expected-error {{declaration of 'str' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:40 {{previous}} +using type = int; + +template extern int var_tpl; // expected-error {{declaration of 'var_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:43 {{previous}} +template int func_tpl(); // expected-error {{declaration of 'func_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:45 {{previous}} +template struct str_tpl; // expected-error {{declaration of 'str_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:46 {{previous}} +template using type_tpl = int; // expected-error {{declaration of 'type_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:47 {{previous}} + +typedef int type; +namespace ns { using ::func; } +namespace ns_alias = ns; +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -9,7 +9,6 @@ // RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface -fmodule-file=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm // // Module implementation for unknown and known module. (The former is ill-formed.) -// FIXME: TEST=1 should fail because we don't have an interface for module z. // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ // RUN: -DTEST=1 -DEXPORT= -DPARTITION= -DMODULE_NAME=z // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ @@ -32,11 +31,11 @@ // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ // RUN: -DTEST=7 -DEXPORT= -DPARTITION=elderberry -DMODULE_NAME=z // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=8 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[]]' +// RUN: -DTEST=8 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[]]' // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=9 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[fancy]]' +// RUN: -DTEST=9 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[fancy]]' // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=10 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[maybe_unused]]' +// RUN: -DTEST=10 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[maybe_unused]]' EXPORT module PARTITION MODULE_NAME; #if TEST == 4 @@ -45,11 +44,13 @@ #elif TEST == 6 // expected-error@-5 {{module partition must be declared 'export'}} #elif TEST == 7 -// expected-error@-7 {{expected ';'}} expected-error@-7 {{requires a type specifier}} +// expected-error@-7 {{expected ';'}} expected-error@-7 {{requires a type specifier}} expected-error@-7 {{definition of module 'elderberry' is not available}} #elif TEST == 9 // expected-warning@-9 {{unknown attribute 'fancy' ignored}} #elif TEST == 10 // expected-error-re@-11 {{'maybe_unused' attribute cannot be applied to a module{{$}}}} +#elif TEST == 1 +// expected-error@-13 {{definition of module 'z' is not available}} #else // expected-no-diagnostics #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -9,12 +9,15 @@ // RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %t/a.b.cppm -o %t/a.b.pcm // // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -fmodule-file=%t/a.b.pcm -verify %s \ -// RUN: -DMODULE_NAME=z +// RUN: -DMODULE_NAME=z -DINTERFACE // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -fmodule-file=%t/a.b.pcm -verify %s \ // RUN: -DMODULE_NAME=a.b // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -fmodule-file=%t/a.b.pcm -verify %s \ // RUN: -DMODULE_X -DMODULE_NAME=x +#ifdef INTERFACE +export +#endif module MODULE_NAME; int use_1 = a; diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,27 +1,28 @@ // RUN: %clang_cc1 -fmodules-ts %s -verify -o /dev/null -// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -verify -o /dev/null -// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -verify -o /dev/null +// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -verify -emit-module-interface -o %t +// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -verify -fmodule-file=%t -o /dev/null // // RUN: %clang_cc1 -fmodules-ts %s -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null // RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null // RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null #if INTERFACE +// expected-no-diagnostics export module A; #elif IMPLEMENTATION module A; #ifdef BUILT_AS_INTERFACE // expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}} + #define INTERFACE #endif #else #ifdef BUILT_AS_INTERFACE - // FIXME: Diagnose missing module declaration (at end of TU) + // expected-error@1 {{missing 'export module' declaration in module interface unit}} #endif #endif -export int a; #ifndef INTERFACE -// expected-error@-2 {{export declaration can only be used within a module interface unit}} +export int b; // expected-error {{export declaration can only be used within a module interface unit}} #else -// expected-no-diagnostics +export int a; #endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p1.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p1.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p1.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p1.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++17 -fmodules-ts -verify %s -DFOO=export -DBAR=export +// RUN: %clang_cc1 -std=c++17 -fmodules-ts -verify %s -DFOO=export -DBAR= +// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s -DFOO=export -emit-module-interface -o %t +// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s -fmodule-file=%t -DFOO= +// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s -fmodule-file=%t -DBAR=export +// RUN: %clang_cc1 -std=c++17 -fmodules-ts -verify %s -fmodule-file=%t -DFOO= -DBAR=export + +#ifdef FOO +FOO module foo; // expected-note {{previous module declaration is here}} +#endif + +#ifdef BAR +BAR module bar; // expected-error {{translation unit contains multiple module declarations}} +#endif diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p2.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p2.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p2.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/p2.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fmodules-ts -verify %s + +// A named module shall contain exactly one module interface unit. +module M; // expected-error {{definition of module 'M' is not available; use -fmodule-file= to specify path to precompiled module interface}} + +// FIXME: How do we ensure there is not more than one? diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/baremetal.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/baremetal.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/baremetal.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/baremetal.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -10,7 +10,7 @@ // CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include" // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp" -// CHECK-V6M-C-NEXT: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-C-NEXT: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-V6M-C-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" @@ -32,7 +32,7 @@ // RUN: -target armv6m-none-eabi \ // RUN: --sysroot=%S/Inputs/baremetal_arm \ // RUN: | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s -// CHECK-V6M-DEFAULTCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-DEFAULTCXX: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind" // CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" @@ -45,7 +45,7 @@ // RUN: | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s // CHECK-V6M-LIBCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}{{[^v].*}}" // CHECK-V6M-LIBCXX: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" -// CHECK-V6M-LIBCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-LIBCXX: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind" // CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" @@ -58,7 +58,7 @@ // RUN: | FileCheck --check-prefix=CHECK-V6M-LIBSTDCXX %s // CHECK-V6M-LIBSTDCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-V6M-LIBSTDCXX: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}6.0.0" -// CHECK-V6M-LIBSTDCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-LIBSTDCXX: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind" // CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" @@ -69,7 +69,7 @@ // RUN: --sysroot=%S/Inputs/baremetal_arm \ // RUN: -nodefaultlibs \ // RUN: | FileCheck --check-prefix=CHECK-V6M-NDL %s -// CHECK-V6M-NDL: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic" +// CHECK-V6M-NDL: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-V6M-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" "-o" "{{.*}}.o" // RUN: %clangxx -target arm-none-eabi -v 2>&1 \ diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/clang_f_opts.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/clang_f_opts.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/clang_f_opts.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/clang_f_opts.c 2017-10-17 14:41:55.000000000 +0000 @@ -1,7 +1,7 @@ // REQUIRES: clang-driver // RUN: %clang -### -S -fasm -fblocks -fbuiltin -fno-math-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fmath-errno -fno-common -fno-pascal-strings -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fsplit-stack %s 2>&1 | FileCheck -check-prefix=CHECK-OPTIONS1 %s -// RUN: %clang -### -S -fasm -fblocks -fbuiltin -fno-math-errno -fcommon -fpascal-strings -fno-asm -fno-blocks -fno-builtin -fmath-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-enums -fshort-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-OPTIONS2 %s +// RUN: %clang -### -S -fasm -fblocks -fbuiltin -fno-math-errno -fcommon -fpascal-strings -fno-asm -fno-blocks -fno-builtin -fmath-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-enums %s 2>&1 | FileCheck -check-prefix=CHECK-OPTIONS2 %s // CHECK-OPTIONS1: -split-stacks // CHECK-OPTIONS1: -fgnu-keywords @@ -12,7 +12,6 @@ // CHECK-OPTIONS2: -fno-gnu-keywords // CHECK-OPTIONS2: -fno-builtin // CHECK-OPTIONS2: -fshort-enums -// CHECK-OPTIONS2: -fshort-wchar // CHECK-OPTIONS2: -fno-common // CHECK-OPTIONS2: -fno-show-source-location @@ -466,15 +465,15 @@ // RUN: %clang -### -S -fno-unsigned-char %s 2>&1 | FileCheck -check-prefix=CHAR-SIGN4 %s // CHAR-SIGN4-NOT: -fno-signed-char -// RUN: %clang -### -fshort-wchar -fno-short-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-WCHAR1 -check-prefix=DELIMITERS %s -// RUN: %clang -### -fno-short-wchar -fshort-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-WCHAR2 -check-prefix=DELIMITERS %s +// RUN: %clang -target x86_64-unknown-none-none -### -fshort-wchar -fno-short-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-WCHAR1 -check-prefix=DELIMITERS %s +// RUN: %clang -target x86_64-unknown-none-none -### -fno-short-wchar -fshort-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-WCHAR2 -check-prefix=DELIMITERS %s // Make sure we don't match the -NOT lines with the linker invocation. // Delimiters match the start of the cc1 and the start of the linker lines // DELIMITERS: {{^ *"}} -// CHECK-WCHAR1: -fno-short-wchar -// CHECK-WCHAR1-NOT: -fshort-wchar -// CHECK-WCHAR2: -fshort-wchar -// CHECK-WCHAR2-NOT: -fno-short-wchar +// CHECK-WCHAR1: -fwchar-type=int +// CHECK-WCHAR1-NOT: -fwchar-type=short +// CHECK-WCHAR2: -fwchar-type=short +// CHECK-WCHAR2-NOT: -fwchar-type=int // DELIMITERS: {{^ *"}} // RUN: %clang -### -fno-experimental-new-pass-manager -fexperimental-new-pass-manager %s 2>&1 | FileCheck --check-prefix=CHECK-PM --check-prefix=CHECK-NEW-PM %s @@ -499,3 +498,8 @@ // RUN: %clang -### -S -fno-allow-editor-placeholders %s 2>&1 | FileCheck -check-prefix=CHECK-NO-ALLOW-PLACEHOLDERS %s // CHECK-ALLOW-PLACEHOLDERS: -fallow-editor-placeholders // CHECK-NO-ALLOW-PLACEHOLDERS-NOT: -fallow-editor-placeholders + +// RUN: %clang -### -target x86_64-unknown-windows-msvc -fno-short-wchar %s 2>&1 | FileCheck -check-prefix CHECK-WINDOWS-ISO10646 %s +// CHECK-WINDOWS-ISO10646: "-fwchar-type=int" +// CHECK-WINDOWS-ISO10646: "-fsigned-wchar" + diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/cl-options.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/cl-options.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/cl-options.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/cl-options.c 2017-10-17 14:41:55.000000000 +0000 @@ -520,8 +520,11 @@ // RUN: %clang_cl -fmsc-version=1900 -TP -std:c++14 -### -- %s 2>&1 | FileCheck -check-prefix=STDCXX14 %s // STDCXX14: -std=c++14 +// RUN: %clang_cl -fmsc-version=1900 -TP -std:c++17 -### -- %s 2>&1 | FileCheck -check-prefix=STDCXX17 %s +// STDCXX17: -std=c++17 + // RUN: %clang_cl -fmsc-version=1900 -TP -std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=STDCXXLATEST %s -// STDCXXLATEST: -std=c++1z +// STDCXXLATEST: -std=c++2a // RUN: env CL="/Gy" %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=ENV-CL %s // ENV-CL: "-ffunction-sections" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/cuda-detect.cu llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/cuda-detect.cu --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/cuda-detect.cu 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/cuda-detect.cu 2017-10-17 14:41:55.000000000 +0000 @@ -2,7 +2,7 @@ // REQUIRES: x86-registered-target // REQUIRES: nvptx-registered-target // -// # Check that we properly detect CUDA installation. +// Check that we properly detect CUDA installation. // RUN: %clang -v --target=i386-unknown-linux \ // RUN: --sysroot=%S/no-cuda-there 2>&1 | FileCheck %s -check-prefix NOCUDA // RUN: %clang -v --target=i386-apple-macosx \ @@ -18,6 +18,19 @@ // RUN: %clang -v --target=i386-apple-macosx \ // RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 | FileCheck %s +// Check that we don't find a CUDA installation without libdevice ... +// RUN: %clang -v --target=i386-unknown-linux \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: %clang -v --target=i386-apple-macosx \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NOCUDA + +// ... unless the user doesn't need libdevice +// RUN: %clang -v --target=i386-unknown-linux -nocudalib \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE +// RUN: %clang -v --target=i386-apple-macosx -nocudalib \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE + + // Make sure we map libdevice bitcode files to proper GPUs. These // tests use Inputs/CUDA_80 which has full set of libdevice files. // However, libdevice mapping only matches CUDA-7.x at the moment. @@ -112,6 +125,7 @@ // RUN: | FileCheck %s --check-prefix CHECK-CXXINCLUDE // CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA/usr/local/cuda +// NO-LIBDEVICE: Found CUDA installation: {{.*}}/Inputs/CUDA-nolibdevice/usr/local/cuda // NOCUDA-NOT: Found CUDA installation: // MISSINGLIBDEVICE: error: cannot find libdevice for sm_20. diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/darwin-ld.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/darwin-ld.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/darwin-ld.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/darwin-ld.c 2017-10-17 14:41:55.000000000 +0000 @@ -351,3 +351,17 @@ // RUN: %clang -target arm64-apple-ios5.0 -miphoneos-version-min=5.0 -fprofile-instr-generate -### %t.o 2> %t.log // RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log // LINK_PROFILE_FIRST: {{ld(.exe)?"}} "{{[^"]+}}libclang_rt.profile_{{[a-z]+}}.a" + +// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Wl,-exported_symbols_list,/dev/null -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log +// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Wl,-exported_symbol,foo -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log +// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Xlinker -exported_symbol -Xlinker foo -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log +// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log +// PROFILE_EXPORT: "-exported_symbol" "_VPMergeHook" "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename" +// +// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log +// NO_PROFILE_EXPORT-NOT: "-exported_symbol" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/gold-lto-new-pass-man.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/gold-lto-new-pass-man.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/gold-lto-new-pass-man.c 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/gold-lto-new-pass-man.c 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,7 @@ +// RUN: touch %t.o +// +// RUN: %clang -target ppc64le-unknown-linux -### %t.o -flto 2>&1 \ +// RUN: -Wl,-plugin-opt=foo -O3 \ +// RUN: -fexperimental-new-pass-manager \ +// RUN: | FileCheck %s +// CHECK: "-plugin-opt=new-pass-manager" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/openmp-offload.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/openmp-offload.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/openmp-offload.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/openmp-offload.c 2017-10-17 14:41:55.000000000 +0000 @@ -64,13 +64,21 @@ /// ########################################################################## /// Check -march=pwr7 is NOT passed to nvptx64-nvidia-cuda. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -march=pwr7 %s 2>&1 \ +// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -target powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-MARCH-TO-GPU %s // CHK-FOPENMP-MARCH-TO-GPU-NOT: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" /// ########################################################################### +/// Check -march=pwr7 is NOT passed to x86_64-unknown-linux-gnu. +// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu -target powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-FOPENMP-MARCH-TO-X86 %s + +// CHK-FOPENMP-MARCH-TO-X86-NOT: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" + +/// ########################################################################### + /// Check -Xopenmp-target triggers error when multiple triples are used. // RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-unknown-linux-gnu -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-AMBIGUOUS-ERROR %s diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/sanitizer-ld.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/sanitizer-ld.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/sanitizer-ld.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/sanitizer-ld.c 2017-10-17 14:41:55.000000000 +0000 @@ -17,10 +17,23 @@ // CHECK-ASAN-LINUX: "-ldl" // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=address -shared-libsan \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-SHARED-ASAN-LINUX %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=address -shared-libasan \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-SHARED-ASAN-LINUX %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=address \ +// RUN: -shared-libsan -static-libsan -shared-libasan \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-SHARED-ASAN-LINUX %s // // CHECK-SHARED-ASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" // CHECK-SHARED-ASAN-LINUX-NOT: "-lc" @@ -34,7 +47,7 @@ // CHECK-SHARED-ASAN-LINUX-NOT: "--dynamic-list" // RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \ -// RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=address -shared-libasan \ +// RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=address -shared-libsan \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-ASAN-LINUX %s @@ -131,6 +144,39 @@ // CHECK-ASAN-ANDROID-NOT: "-lpthread" // CHECK-ASAN-ANDROID: libclang_rt.asan-arm-android.so" // CHECK-ASAN-ANDROID-NOT: "-lpthread" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: -static-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-ANDROID-STATICLIBASAN %s +// +// CHECK-ASAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-ASAN-ANDROID-STATICLIBASAN: libclang_rt.asan-arm-android.a" +// CHECK-ASAN-ANDROID-STATICLIBASAN: "-lpthread" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=undefined \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-ANDROID %s +// +// CHECK-UBSAN-ANDROID: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-UBSAN-ANDROID-NOT: "-lc" +// CHECK-UBSAN-ANDROID-NOT: "-pie" +// CHECK-UBSAN-ANDROID-NOT: "-lpthread" +// CHECK-UBSAN-ANDROID: libclang_rt.ubsan_standalone-arm-android.so" +// CHECK-UBSAN-ANDROID-NOT: "-lpthread" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=undefined \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: -static-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-ANDROID-STATICLIBASAN %s +// +// CHECK-UBSAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-UBSAN-ANDROID-STATICLIBASAN: libclang_rt.ubsan_standalone-arm-android.a" +// CHECK-UBSAN-ANDROID-STATICLIBASAN: "-lpthread" + // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target i686-linux-android -fuse-ld=ld -fsanitize=address \ @@ -147,10 +193,10 @@ // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target arm-linux-androideabi -fsanitize=address \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: -shared-libasan \ +// RUN: -shared-libsan \ // RUN: | FileCheck --check-prefix=CHECK-ASAN-ANDROID-SHARED-LIBASAN %s // -// CHECK-ASAN-ANDROID-SHARED-LIBASAN-NOT: argument unused during compilation: '-shared-libasan' +// CHECK-ASAN-ANDROID-SHARED-LIBASAN-NOT: argument unused during compilation: '-shared-libsan' // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=address \ @@ -214,6 +260,13 @@ // RUN: -target i386-unknown-linux -fuse-ld=ld \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s + +// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -static-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s + // CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-UBSAN-LINUX-NOT: libclang_rt.asan // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx @@ -223,6 +276,27 @@ // CHECK-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-LINUX: "-lpthread" +// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -shared-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX-SHAREDLIBASAN %s + +// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -static-libsan -shared-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX-SHAREDLIBASAN %s + +// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -shared -shared-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX-SHAREDLIBASAN %s + +// CHECK-UBSAN-LINUX-SHAREDLIBASAN: "{{.*}}ld{{(.exe)?}}" +// CHECK-UBSAN-LINUX-SHAREDLIBASAN: "{{.*}}libclang_rt.ubsan_standalone-i386.so{{.*}}" + // RUN: %clang -fsanitize=undefined -fsanitize-link-c++-runtime %s -### -o %t.o 2>&1 \ // RUN: -target i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ @@ -261,6 +335,13 @@ // CHECK-UBSAN-MINIMAL-DARWIN: "{{.*}}ld{{(.exe)?}}" // CHECK-UBSAN-MINIMAL-DARWIN: "{{.*}}libclang_rt.ubsan_minimal_osx_dynamic.dylib" +// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ +// RUN: -target x86_64-apple-darwin -fuse-ld=ld -static-libsan \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-UBSAN-STATIC-DARWIN %s +// CHECK-UBSAN-STATIC-DARWIN: "{{.*}}ld{{(.exe)?}}" +// CHECK-UBSAN-STATIC-DARWIN: "{{.*}}libclang_rt.ubsan_osx.a" + // RUN: %clang -fsanitize=address,undefined %s -### -o %t.o 2>&1 \ // RUN: -target i386-unknown-linux -fuse-ld=ld \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ @@ -427,6 +508,24 @@ // CHECK-CFI-CROSS-DSO-DIAG-LINUX: "-whole-archive" "{{[^"]*}}libclang_rt.cfi_diag-x86_64.a" "-no-whole-archive" // CHECK-CFI-CROSS-DSO-DIAG-LINUX: -export-dynamic +// Cross-DSO CFI on Android does not link runtime libraries. +// RUN: %clang -fsanitize=cfi -fsanitize-cfi-cross-dso %s -### -o %t.o 2>&1 \ +// RUN: -target aarch64-linux-android -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_android_tree \ +// RUN: | FileCheck --check-prefix=CHECK-CFI-CROSS-DSO-ANDROID %s +// CHECK-CFI-CROSS-DSO-ANDROID: "{{.*}}ld{{(.exe)?}}" +// CHECK-CFI-CROSS-DSO-ANDROID-NOT: libclang_rt. + +// Cross-DSO CFI with diagnostics on Android links just the UBSAN runtime. +// RUN: %clang -fsanitize=cfi -fsanitize-cfi-cross-dso %s -### -o %t.o 2>&1 \ +// RUN: -fno-sanitize-trap=cfi -fsanitize-recover=cfi \ +// RUN: -target aarch64-linux-android -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_android_tree \ +// RUN: | FileCheck --check-prefix=CHECK-CFI-CROSS-DSO-DIAG-ANDROID %s +// CHECK-CFI-CROSS-DSO-DIAG-ANDROID: "{{.*}}ld{{(.exe)?}}" +// CHECK-CFI-CROSS-DSO-DIAG-ANDROID: "{{[^"]*}}libclang_rt.ubsan_standalone-aarch64-android.so" +// CHECK-CFI-CROSS-DSO-DIAG-ANDROID: "-export-dynamic-symbol=__cfi_check" + // RUN: %clangxx -fsanitize=address %s -### -o %t.o 2>&1 \ // RUN: -mmacosx-version-min=10.6 \ // RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ @@ -515,26 +614,6 @@ // CHECK-SAFESTACK-ANDROID-AARCH64: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" // CHECK-SAFESTACK-ANDROID-AARCH64-NOT: libclang_rt.safestack -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=cfi \ -// RUN: --sysroot=%S/Inputs/basic_android_tree \ -// RUN: | FileCheck --check-prefix=CHECK-CFI-ANDROID %s -// -// CHECK-CFI-ANDROID: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-CFI-ANDROID-NOT: libclang_rt.cfi -// CHECK-CFI-ANDROID-NOT: __cfi_check - -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=cfi \ -// RUN: -fsanitize-cfi-cross-dso \ -// RUN: --sysroot=%S/Inputs/basic_android_tree \ -// RUN: | FileCheck --check-prefix=CHECK-CROSSDSO-CFI-ANDROID %s -// -// CHECK-CROSSDSO-CFI-ANDROID: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-CROSSDSO-CFI-ANDROID-NOT: libclang_rt.cfi -// CHECK-CROSSDSO-CFI-ANDROID: -export-dynamic-symbol=__cfi_check -// CHECK-CROSSDSO-CFI-ANDROID-NOT: libclang_rt.cfi - // RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-scei-ps4 -fuse-ld=ld \ // RUN: -shared \ diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/x86-march.c llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/x86-march.c --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Driver/x86-march.c 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Driver/x86-march.c 2017-10-17 14:41:55.000000000 +0000 @@ -52,6 +52,10 @@ // RUN: | FileCheck %s -check-prefix=knl // knl: "-target-cpu" "knl" // +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=knm 2>&1 \ +// RUN: | FileCheck %s -check-prefix=knm +// knm: "-target-cpu" "knm" +// // RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=cannonlake 2>&1 \ // RUN: | FileCheck %s -check-prefix=cannonlake // cannonlake: "-target-cpu" "cannonlake" diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Headers/wchar_limits.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Headers/wchar_limits.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Headers/wchar_limits.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Headers/wchar_limits.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify %s -// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -fshort-wchar %s +// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -fwchar-type=short -fno-signed-wchar %s // expected-no-diagnostics #include diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Index/annotate-attribute.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Index/annotate-attribute.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Index/annotate-attribute.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Index/annotate-attribute.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -16,6 +16,12 @@ void methodWithoutAttribute(); }; +template +class __attribute__((annotate("works"))) TemplateTest {}; + +template +int templateFunction(T value) __attribute__((annotate("works"))); + // CHECK: ClassDecl=Test:3:7 (Definition) Extent=[3:1 - 17:2] // CHECK-NEXT: CXXAccessSpecifier=:4:1 (Definition) Extent=[4:1 - 4:8] // CHECK-NEXT: CXXMethod=aMethod:5:51 Extent=[5:3 - 5:60] @@ -31,3 +37,9 @@ // CHECK-NEXT: CompoundStmt= Extent=[12:23 - 12:25] // CHECK-NEXT: CXXAccessSpecifier=:14:1 (Definition) Extent=[14:1 - 14:11] // CHECK-NEXT: CXXMethod=methodWithoutAttribute:16:8 Extent=[16:3 - 16:32] +// CHECK: ClassTemplate=TemplateTest:20:42 (Definition) Extent=[19:1 - 20:57] +// CHECK-NEXT: TemplateTypeParameter=T:19:20 (Definition) Extent=[19:11 - 19:21] [access=public] +// CHECK-NEXT: attribute(annotate)=works Extent=[20:22 - 20:39] +// CHECK: FunctionTemplate=templateFunction:23:5 Extent=[22:1 - 23:65] +// CHECK-NEXT: TemplateTypeParameter=T:22:20 (Definition) Extent=[22:11 - 22:21] [access=public] +// CHECK-NEXT: attribute(annotate)=works Extent=[23:46 - 23:63] diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Index/index-pch.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Index/index-pch.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Index/index-pch.cpp 2017-10-03 20:04:48.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Index/index-pch.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -1,4 +1,4 @@ -// RUN: c-index-test -write-pch %t.pch -fshort-wchar %s +// RUN: c-index-test -write-pch %t.pch -fwchar-type=short -fno-signed-wchar %s // RUN: env LIBCLANG_NOTHREADS=1 c-index-test -index-tu %t.pch | FileCheck %s // CHECK: [indexDeclaration]: kind: variable | name: wideStr diff -Nru llvm-toolchain-snapshot-6.0~svn314833/clang/test/Index/index-template-template-param.cpp llvm-toolchain-snapshot-6.0~svn316003/clang/test/Index/index-template-template-param.cpp --- llvm-toolchain-snapshot-6.0~svn314833/clang/test/Index/index-template-template-param.cpp 1970-01-01 00:00:00.000000000 +0000 +++ llvm-toolchain-snapshot-6.0~svn316003/clang/test/Index/index-template-template-param.cpp 2017-10-17 14:41:55.000000000 +0000 @@ -0,0 +1,7 @@ +// RUN: c-index-test -index-file %s -x objective-c++ | FileCheck %s + +template class Template1 {}; + +template