diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..d37637e4b9271180d18882f38aa4ef09dbe7f71f --- /dev/null +++ b/.github/workflows/clang-tests.yml @@ -0,0 +1,43 @@ +name: Clang Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - '.github/workflows/clang-tests.yml' + pull_request: + paths: + - 'clang/**' + - 'llvm/**' + - '.github/workflows/clang-tests.yml' + +jobs: + build_clang: + name: clang check-all + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - windows-latest + - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Test clang + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release + build_target: check-clang diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..c7d1993ba006d68b41010b2b72fdca3b8c69dc37 --- /dev/null +++ b/.github/workflows/libclang-abi-tests.yml @@ -0,0 +1,151 @@ +name: libclang ABI Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - '.github/workflows/libclang-abi-tests.yml' + pull_request: + paths: + - 'clang/**' + - '.github/workflows/libclang-abi-tests.yml' + +jobs: + abi-dump-setup: + runs-on: ubuntu-latest + outputs: + BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} + ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} + ABI_LIBS: ${{ steps.vars.outputs.ABI_LIBS }} + BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} + BASELINE_VERSION_MINOR: ${{ steps.vars.outputs.BASELINE_VERSION_MINOR }} + LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} + LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} + steps: + - name: Checkout source + uses: actions/checkout@v1 + with: + fetch-depth: 250 + + - name: Get LLVM version + id: version + uses: llvm/actions/get-llvm-version@main + + - name: Setup Variables + id: vars + run: | + minor_version=0 + remote_repo='https://github.com/llvm/llvm-project' + if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 -o ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then + major_version=$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) + baseline_ref="llvmorg-$major_version.0.0" + + # If there is a minor release, we want to use that as the base line. + minor_ref=`git ls-remote --refs -t $remote_repo llvmorg-$major_version.[1-9].[0-9] | tail -n1 | grep -o 'llvmorg-.\+' || true` + if [ -n "$minor_ref" ]; then + baseline_ref=$minor_ref + else + # Check if we have a release candidate + rc_ref=`git ls-remote --refs -t $remote_repo llvmorg-$major_version.[1-9].[0-9]-rc* | tail -n1 | grep -o 'llvmorg-.\+' || true` + if [ -n "$rc_ref" ]; then + baseline_ref=$rc_ref + fi + fi + echo ::set-output name=BASELINE_VERSION_MAJOR::$major_version + echo ::set-output name=BASELINE_REF::$baseline_ref + echo ::set-output name=ABI_HEADERS::clang-c + echo ::set-output name=ABI_LIBS::libclang.so + else + echo ::set-output name=BASELINE_VERSION_MAJOR::${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + echo ::set-output name=BASELINE_REF::llvmorg-${{ steps.version.outputs.LLVM_VERSION_MAJOR }}.0.0 + echo ::set-output name=ABI_HEADERS::. + echo ::set-output name=ABI_LIBS::libclang.so libclang-cpp.so + fi + + + abi-dump: + needs: abi-dump-setup + runs-on: ubuntu-latest + strategy: + matrix: + name: + - build-baseline + - build-latest + include: + - name: build-baseline + llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} + ref: ${{ needs.abi-dump-setup.outputs.BASELINE_REF }} + repo: llvm/llvm-project + - name: build-latest + llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} + ref: ${{ github.sha }} + repo: ${{ github.repository }} + steps: + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - name: Install abi-compliance-checker + run: | + sudo apt-get install abi-dumper autoconf pkg-config + - name: Install universal-ctags + run: | + git clone https://github.com/universal-ctags/ctags.git + cd ctags + ./autogen.sh + ./configure + sudo make install + - name: Download source code + uses: llvm/actions/get-llvm-project-src@main + with: + ref: ${{ matrix.ref }} + repo: ${{ matrix.repo }} + - name: Configure + run: | + mkdir install + cmake -B build -S llvm -G Ninja -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g1 -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Og" -DCMAKE_INSTALL_PREFIX=`pwd`/install llvm + - name: Build + run: ninja -C build/ ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} install-clang-headers + - name: Dump ABI + run: | + parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} + for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do + # Remove symbol versioning from dumps, so we can compare across major versions. + sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi + done + - name: Upload ABI file + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.name }} + path: "*${{ matrix.ref }}.abi" + + abi-compare: + runs-on: ubuntu-latest + needs: + - abi-dump-setup + - abi-dump + steps: + - name: Download baseline + uses: actions/download-artifact@v1 + with: + name: build-baseline + - name: Download latest + uses: actions/download-artifact@v1 + with: + name: build-latest + + - name: Install abi-compliance-checker + run: sudo apt-get install abi-compliance-checker + - name: Compare ABI + run: | + for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do + abi-compliance-checker -lib $lib -old build-baseline/$lib*.abi -new build-latest/$lib*.abi + done + - name: Upload ABI Comparison + if: always() + uses: actions/upload-artifact@v2 + with: + name: compat-report-${{ github.sha }} + path: compat_reports/ + diff --git a/.github/workflows/libclc-tests.yml b/.github/workflows/libclc-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..6be01c839f4438645e9ad9984821cd53e08b00d6 --- /dev/null +++ b/.github/workflows/libclc-tests.yml @@ -0,0 +1,53 @@ +name: libclc Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - 'libclc/**' + - '.github/workflows/libclc-tests.yml' + pull_request: + paths: + - 'clang/**' + - 'llvm/**' + - 'libclc/**' + - '.github/workflows/libclc-tests.yml' + +jobs: + build_libclc: + name: libclc test + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # Disable build on windows, because I can't figure out where llvm-config is. + #- windows-latest + - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Build clang + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release + build_target: "" + - name: Build and test libclc + # spirv targets require llvm-spirv, so skip building them until we figure out + # how to install this tool. + run: | + cmake -G Ninja -S libclc -B libclc-build -DLLVM_CONFIG=`pwd`/build/bin/llvm-config -DLIBCLC_TARGETS_TO_BUILD="amdgcn--;amdgcn--amdhsa;r600--;nvptx--;nvptx64--;nvptx--nvidiacl;nvptx64--nvidiacl" + ninja -C libclc-build + ninja -C libclc-build test diff --git a/.github/workflows/lld-tests.yml b/.github/workflows/lld-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..1e5540d2fc4dee66c86c18783cfc43628e57a3fd --- /dev/null +++ b/.github/workflows/lld-tests.yml @@ -0,0 +1,43 @@ +name: LLD Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'lld/**' + - 'llvm/**' + - '.github/workflows/lld-tests.yml' + pull_request: + paths: + - 'lld/**' + - 'llvm/**' + - '.github/workflows/lld-tests.yml' + +jobs: + build_lld: + name: lld check-all + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - windows-latest + - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Test lld + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="lld" -DCMAKE_BUILD_TYPE=Release + build_target: check-lld diff --git a/.github/workflows/lldb-tests.yml b/.github/workflows/lldb-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..1658c0e001a01efd67f1cc8d301c96335f9b4bf1 --- /dev/null +++ b/.github/workflows/lldb-tests.yml @@ -0,0 +1,50 @@ +name: lldb Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - 'lldb/**' + - '.github/workflows/lldb-tests.yml' + pull_request: + paths: + - 'clang/**' + - 'llvm/**' + - 'lldb/**' + - '.github/workflows/lldb-tests.yml' + +jobs: + build_lldb: + name: lldb build + runs-on: ${{ matrix.os }} + # Workaround for build faliure on Mac OS X: llvm.org/PR46190, https://github.com/actions/virtual-environments/issues/2274 + env: + CPLUS_INCLUDE_PATH: /usr/local/opt/llvm/include/c++/v1:/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - windows-latest + - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Build lldb + uses: llvm/actions/build-test-llvm-project@main + with: + # Mac OS requries that libcxx is enabled for lldb tests, so we need to disable them. + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="clang;lldb" -DCMAKE_BUILD_TYPE=Release -DLLDB_INCLUDE_TESTS=OFF + # check-lldb is not consistent, so we only build lldb. + build_target: "" diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..bb011c0dafbb29634ca7f365dcb150605a5d273f --- /dev/null +++ b/.github/workflows/llvm-tests.yml @@ -0,0 +1,178 @@ +name: LLVM Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'llvm/**' + - '.github/workflows/llvm-tests.yml' + pull_request: + paths: + - 'llvm/**' + - '.github/workflows/llvm-tests.yml' + +jobs: + build_llvm: + name: llvm check-all + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - windows-latest + - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Test llvm + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DCMAKE_BUILD_TYPE=Release + + abi-dump-setup: + runs-on: ubuntu-latest + outputs: + BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} + ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} + BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} + LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} + LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} + steps: + - name: Checkout source + uses: actions/checkout@v1 + with: + fetch-depth: 250 + + - name: Get LLVM version + id: version + uses: llvm/actions/get-llvm-version@main + + - name: Setup Variables + id: vars + run: | + if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 -o ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then + echo ::set-output name=BASELINE_VERSION_MAJOR::$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) + echo ::set-output name=ABI_HEADERS::llvm-c + else + echo ::set-output name=BASELINE_VERSION_MAJOR::${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + echo ::set-output name=ABI_HEADERS::. + fi + + abi-dump: + needs: abi-dump-setup + runs-on: ubuntu-latest + strategy: + matrix: + name: + - build-baseline + - build-latest + include: + - name: build-baseline + llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} + ref: llvmorg-${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }}.0.0 + repo: llvm/llvm-project + - name: build-latest + llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} + ref: ${{ github.sha }} + repo: ${{ github.repository }} + steps: + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - name: Install abi-compliance-checker + run: | + sudo apt-get install abi-dumper autoconf pkg-config + - name: Install universal-ctags + run: | + git clone https://github.com/universal-ctags/ctags.git + cd ctags + ./autogen.sh + ./configure + sudo make install + - name: Download source code + uses: llvm/actions/get-llvm-project-src@main + with: + ref: ${{ matrix.ref }} + repo: ${{ matrix.repo }} + - name: Configure + run: | + mkdir install + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g1 -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Og" -DCMAKE_INSTALL_PREFIX=`pwd`/install llvm + - name: Build + # Need to run install-LLVM twice to ensure the symlink is installed (this is a bug). + run: | + ninja -C build install-LLVM + ninja -C build install-LLVM + ninja -C build install-llvm-headers + - name: Dump ABI + run: | + if [ "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" ]; then + nm ./install/lib/libLLVM.so | awk "/T _LLVM/ || /T LLVM/ { print $3 }" | sort -u | sed -e "s/^_//g" | cut -d ' ' -f 3 > llvm.symbols + # Even though the -symbols-list option doesn't seem to filter out the symbols, I believe it speeds up processing, so I'm leaving it in. + export EXTRA_ARGS="-symbols-list llvm.symbols" + else + touch llvm.symbols + fi + abi-dumper $EXTRA_ARGS -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o ${{ matrix.ref }}.abi ./install/lib/libLLVM.so + # Remove symbol versioning from dumps, so we can compare across major versions. + sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' ${{ matrix.ref }}.abi + - name: Upload ABI file + uses: actions/upload-artifact@v1 + with: + name: ${{ matrix.name }} + path: ${{ matrix.ref }}.abi + + - name: Upload symbol list file + if: matrix.name == 'build-baseline' + uses: actions/upload-artifact@v1 + with: + name: symbol-list + path: llvm.symbols + + abi-compare: + runs-on: ubuntu-latest + needs: + - abi-dump-setup + - abi-dump + steps: + - name: Download baseline + uses: actions/download-artifact@v1 + with: + name: build-baseline + - name: Download latest + uses: actions/download-artifact@v1 + with: + name: build-latest + - name: Download symbol list + uses: actions/download-artifact@v1 + with: + name: symbol-list + + - name: Install abi-compliance-checker + run: sudo apt-get install abi-compliance-checker + - name: Compare ABI + run: | + if [ -s symbol-list/llvm.symbols ]; then + # This option doesn't seem to work with the ABI dumper, so passing it here. + export EXTRA_ARGS="-symbols-list symbol-list/llvm.symbols" + fi + # FIXME: Reading of gzip'd abi files on the GitHub runners stop + # working some time in March of 2021, likely due to a change in the + # runner's environment. + abi-compliance-checker $EXTRA_ARGS -l libLLVM.so -old build-baseline/*.abi -new build-latest/*.abi || test "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" + - name: Upload ABI Comparison + if: always() + uses: actions/upload-artifact@v1 + with: + name: compat-report-${{ github.sha }} + path: compat_reports/ diff --git a/.github/workflows/main-branch-sync.yml b/.github/workflows/main-branch-sync.yml deleted file mode 100644 index 5ea360e281d6154b32ec5b86d361935b546430d3..0000000000000000000000000000000000000000 --- a/.github/workflows/main-branch-sync.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: main branch sync - -on: - push: - branches: - - 'main' - -jobs: - branch_sync: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v2 - with: - # persist-credentials: false allows us to use our own credentials for - # pushing to the repository. Otherwise, the default github actions token - # is used. - persist-credentials: false - fetch-depth: 0 - - - name: Update branch - env: - LLVMBOT_TOKEN: ${{ secrets.LLVMBOT_MAIN_SYNC }} - run: | - git push https://$LLVMBOT_TOKEN@github.com/${{ github.repository }} HEAD:master diff --git a/.gitignore b/.gitignore index b33fbbf932379988c37b1378082600237a9f2745..75e49e68d3b7d8fe1bc930ab1f085c4d63c14d68 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,10 @@ # Nested build directory /build* +# Nested install directory +/install* + + #==============================================================================# # Explicit files to ignore (only matches one). #==============================================================================# diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index a9f5b3e0c15bc15dda2fe9892954f4db2b4395b8..39c2c552eb73e11f25e16bbbc58716568b83b6d2 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -13,7 +13,6 @@ add_clang_library(clangTidyCppCoreGuidelinesModule NarrowingConversionsCheck.cpp NoMallocCheck.cpp OwningMemoryCheck.cpp - PreferMemberInitializerCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp ProBoundsConstantArrayIndexCheck.cpp ProBoundsPointerArithmeticCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index bf613109f0ebd05b6f4b0d1f8abef4c52ad1f716..4cb5022888d3d23676d1607f08f167c8b8ded3e9 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -22,7 +22,6 @@ #include "NarrowingConversionsCheck.h" #include "NoMallocCheck.h" #include "OwningMemoryCheck.h" -#include "PreferMemberInitializerCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" #include "ProBoundsConstantArrayIndexCheck.h" #include "ProBoundsPointerArithmeticCheck.h" @@ -67,8 +66,6 @@ public: "cppcoreguidelines-non-private-member-variables-in-classes"); CheckFactories.registerCheck( "cppcoreguidelines-owning-memory"); - CheckFactories.registerCheck( - "cppcoreguidelines-prefer-member-initializer"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp deleted file mode 100644 index 2d7500943860176c48d8f54ffea1e25b73a8a065..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//===--- PreferMemberInitializerCheck.cpp - clang-tidy -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "PreferMemberInitializerCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Lex/Lexer.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace cppcoreguidelines { - -static bool isControlStatement(const Stmt *S) { - return isa(S); -} - -static bool isNoReturnCallStatement(const Stmt *S) { - const auto *Call = dyn_cast(S); - if (!Call) - return false; - - const FunctionDecl *Func = Call->getDirectCallee(); - if (!Func) - return false; - - return Func->isNoReturn(); -} - -static bool isLiteral(const Expr *E) { - return isa(E); -} - -static bool isUnaryExprOfLiteral(const Expr *E) { - if (const auto *UnOp = dyn_cast(E)) - return isLiteral(UnOp->getSubExpr()); - return false; -} - -static bool shouldBeDefaultMemberInitializer(const Expr *Value) { - if (isLiteral(Value) || isUnaryExprOfLiteral(Value)) - return true; - - if (const auto *DRE = dyn_cast(Value)) - return isa(DRE->getDecl()); - - return false; -} - -static const std::pair -isAssignmentToMemberOf(const RecordDecl *Rec, const Stmt *S) { - if (const auto *BO = dyn_cast(S)) { - if (BO->getOpcode() != BO_Assign) - return std::make_pair(nullptr, nullptr); - - const auto *ME = dyn_cast(BO->getLHS()->IgnoreParenImpCasts()); - if (!ME) - return std::make_pair(nullptr, nullptr); - - const auto *Field = dyn_cast(ME->getMemberDecl()); - if (!Field) - return std::make_pair(nullptr, nullptr); - - if (isa(ME->getBase())) - return std::make_pair(Field, BO->getRHS()->IgnoreParenImpCasts()); - } else if (const auto *COCE = dyn_cast(S)) { - if (COCE->getOperator() != OO_Equal) - return std::make_pair(nullptr, nullptr); - - const auto *ME = - dyn_cast(COCE->getArg(0)->IgnoreParenImpCasts()); - if (!ME) - return std::make_pair(nullptr, nullptr); - - const auto *Field = dyn_cast(ME->getMemberDecl()); - if (!Field) - return std::make_pair(nullptr, nullptr); - - if (isa(ME->getBase())) - return std::make_pair(Field, COCE->getArg(1)->IgnoreParenImpCasts()); - } - - return std::make_pair(nullptr, nullptr); -} - -PreferMemberInitializerCheck::PreferMemberInitializerCheck( - StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - IsUseDefaultMemberInitEnabled( - Context->isCheckEnabled("modernize-use-default-member-init")), - UseAssignment(OptionsView("modernize-use-default-member-init", - Context->getOptions().CheckOptions, Context) - .get("UseAssignment", false)) {} - -void PreferMemberInitializerCheck::storeOptions( - ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "UseAssignment", UseAssignment); -} - -void PreferMemberInitializerCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher( - cxxConstructorDecl(hasBody(compoundStmt()), unless(isInstantiated())) - .bind("ctor"), - this); -} - -void PreferMemberInitializerCheck::check( - const MatchFinder::MatchResult &Result) { - const auto *Ctor = Result.Nodes.getNodeAs("ctor"); - const auto *Body = cast(Ctor->getBody()); - - const CXXRecordDecl *Class = Ctor->getParent(); - SourceLocation InsertPos; - bool FirstToCtorInits = true; - - for (const Stmt *S : Body->body()) { - if (S->getBeginLoc().isMacroID()) { - StringRef MacroName = - Lexer::getImmediateMacroName(S->getBeginLoc(), *Result.SourceManager, - getLangOpts()); - if (MacroName.contains_lower("assert")) - return; - } - if (isControlStatement(S)) - return; - - if (isNoReturnCallStatement(S)) - return; - - if (const auto *CondOp = dyn_cast(S)) { - if (isNoReturnCallStatement(CondOp->getLHS()) || - isNoReturnCallStatement(CondOp->getRHS())) - return; - } - - const FieldDecl *Field; - const Expr *InitValue; - std::tie(Field, InitValue) = isAssignmentToMemberOf(Class, S); - if (Field) { - if (IsUseDefaultMemberInitEnabled && getLangOpts().CPlusPlus11 && - Ctor->isDefaultConstructor() && - (getLangOpts().CPlusPlus20 || !Field->isBitField()) && - (!isa(Class->getDeclContext()) || - !cast(Class->getDeclContext())->isUnion()) && - shouldBeDefaultMemberInitializer(InitValue)) { - auto Diag = - diag(S->getBeginLoc(), "%0 should be initialized in an in-class" - " default member initializer") - << Field; - - SourceLocation FieldEnd = - Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0, - *Result.SourceManager, getLangOpts()); - Diag << FixItHint::CreateInsertion(FieldEnd, - UseAssignment ? " = " : "{") - << FixItHint::CreateInsertionFromRange( - FieldEnd, - CharSourceRange(InitValue->getSourceRange(), true)) - << FixItHint::CreateInsertion(FieldEnd, UseAssignment ? "" : "}"); - - SourceLocation SemiColonEnd = - Lexer::findNextToken(S->getEndLoc(), *Result.SourceManager, - getLangOpts()) - ->getEndLoc(); - CharSourceRange StmtRange = - CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd); - - Diag << FixItHint::CreateRemoval(StmtRange); - } else { - auto Diag = - diag(S->getBeginLoc(), "%0 should be initialized in a member" - " initializer of the constructor") - << Field; - - bool AddComma = false; - if (!Ctor->getNumCtorInitializers() && FirstToCtorInits) { - SourceLocation BodyPos = Ctor->getBody()->getBeginLoc(); - SourceLocation NextPos = Ctor->getBeginLoc(); - do { - InsertPos = NextPos; - NextPos = Lexer::findNextToken(NextPos, *Result.SourceManager, - getLangOpts()) - ->getLocation(); - } while (NextPos != BodyPos); - InsertPos = Lexer::getLocForEndOfToken( - InsertPos, 0, *Result.SourceManager, getLangOpts()); - - Diag << FixItHint::CreateInsertion(InsertPos, " : "); - } else { - bool Found = false; - for (const auto *Init : Ctor->inits()) { - if (Init->isMemberInitializer()) { - if (Result.SourceManager->isBeforeInTranslationUnit( - Field->getLocation(), Init->getMember()->getLocation())) { - InsertPos = Init->getSourceLocation(); - Found = true; - break; - } - } - } - - if (!Found) { - if (Ctor->getNumCtorInitializers()) { - InsertPos = Lexer::getLocForEndOfToken( - (*Ctor->init_rbegin())->getSourceRange().getEnd(), 0, - *Result.SourceManager, getLangOpts()); - } - Diag << FixItHint::CreateInsertion(InsertPos, ", "); - } else { - AddComma = true; - } - } - Diag << FixItHint::CreateInsertion(InsertPos, Field->getName()) - << FixItHint::CreateInsertion(InsertPos, "(") - << FixItHint::CreateInsertionFromRange( - InsertPos, - CharSourceRange(InitValue->getSourceRange(), true)) - << FixItHint::CreateInsertion(InsertPos, ")"); - if (AddComma) - Diag << FixItHint::CreateInsertion(InsertPos, ", "); - - SourceLocation SemiColonEnd = - Lexer::findNextToken(S->getEndLoc(), *Result.SourceManager, - getLangOpts()) - ->getEndLoc(); - CharSourceRange StmtRange = - CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd); - - Diag << FixItHint::CreateRemoval(StmtRange); - FirstToCtorInits = false; - } - } - } -} - -} // namespace cppcoreguidelines -} // namespace tidy -} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h deleted file mode 100644 index dbef7c98d8e3557a84e495db46f12468e296601e..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h +++ /dev/null @@ -1,41 +0,0 @@ -//===--- PreferMemberInitializerCheck.h - clang-tidy ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERMEMBERINITIALIZERCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERMEMBERINITIALIZERCHECK_H - -#include "../ClangTidyCheck.h" - -namespace clang { -namespace tidy { -namespace cppcoreguidelines { - -/// Finds member initializations in the constructor body which can be placed -/// into the initialization list instead. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.html -class PreferMemberInitializerCheck : public ClangTidyCheck { -public: - PreferMemberInitializerCheck(StringRef Name, ClangTidyContext *Context); - bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - return LangOpts.CPlusPlus; - } - void storeOptions(ClangTidyOptions::OptionMap &Opts) override; - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - - const bool IsUseDefaultMemberInitEnabled; - const bool UseAssignment; -}; - -} // namespace cppcoreguidelines -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERMEMBERINITIALIZERCHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index d33040a00e1501a1fc00618fcce5e852e96b3c7f..867b074ca6dbdfbef52f1c9a83f92ef53819fe1d 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -352,6 +352,10 @@ static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, return false; if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none) return false; + // If the function doesn't have a name thats an identifier, can occur of the + // function is an operator overload, bail out early. + if (!FDecl->getDeclName().isIdentifier()) + return false; enum MainType { None, Main, WMain }; auto IsCharPtrPtr = [](QualType QType) -> MainType { if (QType.isNull()) diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index dc89ebd59fe25ab137ff59ae6d5d0ae51d6d6af3..35aed2166f038d6e1d9e5de444567c6328e30e73 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -510,6 +510,11 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, "semanticTokens request, choosing the latter (no notifications)."); Opts.TheiaSemanticHighlighting = false; } + if (Opts.TheiaSemanticHighlighting) { + log("Using legacy semanticHighlights notification, which will be removed " + "in clangd 13. Clients should use the standard semanticTokens " + "request instead."); + } if (Params.rootUri && *Params.rootUri) Opts.WorkspaceRoot = std::string(Params.rootUri->file()); diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index 44ca283b6a0e2f55ec490985da820cf14a8069f7..391632cb086acef45e42d7543ae868854cea5407 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -90,6 +90,13 @@ struct Config { struct { bool SuppressAll = false; llvm::StringSet<> Suppress; + + /// Configures what clang-tidy checks to run and options to use with them. + struct { + // A comma-seperated list of globs specify which clang-tidy checks to run. + std::string Checks; + llvm::StringMap CheckOptions; + } ClangTidy; } Diagnostics; /// Style of the codebase. @@ -99,14 +106,6 @@ struct Config { // ::). All nested namespaces are affected as well. std::vector FullyQualifiedNamespaces; } Style; - - /// Configures what clang-tidy checks to run and options to use with them. - struct { - // A comma-seperated list of globs to specify which clang-tidy checks to - // run. - std::string Checks; - llvm::StringMap CheckOptions; - } ClangTidy; }; } // namespace clangd diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index e82c6e159421c76ea96324b108b001944ff9009a..7d5466778a81d52c242aee1dd8273b1fcc4541f8 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -31,6 +31,7 @@ #include "Features.inc" #include "TidyProvider.h" #include "support/Logger.h" +#include "support/Path.h" #include "support/Trace.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -100,10 +101,13 @@ struct FragmentCompiler { llvm::SourceMgr *SourceMgr; // Normalized Fragment::SourceInfo::Directory. std::string FragmentDirectory; + bool Trusted = false; - llvm::Optional compileRegex(const Located &Text) { + llvm::Optional + compileRegex(const Located &Text, + llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags) { std::string Anchored = "^(" + *Text + ")$"; - llvm::Regex Result(Anchored); + llvm::Regex Result(Anchored, Flags); std::string RegexError; if (!Result.isValid(RegexError)) { diag(Error, "Invalid regex " + Anchored + ": " + RegexError, Text.Range); @@ -180,6 +184,7 @@ struct FragmentCompiler { } void compile(Fragment &&F) { + Trusted = F.Source.Trusted; if (!F.Source.Directory.empty()) { FragmentDirectory = llvm::sys::path::convert_to_slash(F.Source.Directory); if (FragmentDirectory.back() != '/') @@ -189,16 +194,21 @@ struct FragmentCompiler { compile(std::move(F.CompileFlags)); compile(std::move(F.Index)); compile(std::move(F.Diagnostics)); - compile(std::move(F.ClangTidy)); } void compile(Fragment::IfBlock &&F) { if (F.HasUnrecognizedCondition) Out.Conditions.push_back([&](const Params &) { return false; }); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + llvm::Regex::RegexFlags Flags = llvm::Regex::IgnoreCase; +#else + llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags; +#endif + auto PathMatch = std::make_unique>(); for (auto &Entry : F.PathMatch) { - if (auto RE = compileRegex(Entry)) + if (auto RE = compileRegex(Entry, Flags)) PathMatch->push_back(std::move(*RE)); } if (!PathMatch->empty()) { @@ -219,7 +229,7 @@ struct FragmentCompiler { auto PathExclude = std::make_unique>(); for (auto &Entry : F.PathExclude) { - if (auto RE = compileRegex(Entry)) + if (auto RE = compileRegex(Entry, Flags)) PathExclude->push_back(std::move(*RE)); } if (!PathExclude->empty()) { @@ -311,10 +321,18 @@ struct FragmentCompiler { void compile(Fragment::IndexBlock::ExternalBlock &&External, llvm::SMRange BlockRange) { + if (External.Server && !Trusted) { + diag(Error, + "Remote index may not be specified by untrusted configuration. " + "Copy this into user config to use it.", + External.Server->Range); + return; + } #ifndef CLANGD_ENABLE_REMOTE if (External.Server) { - diag(Error, "Clangd isn't compiled with remote index support, ignoring " - "Server." External.Server->Range); + elog("Clangd isn't compiled with remote index support, ignoring Server: " + "{0}", + *External.Server); External.Server.reset(); } #endif @@ -350,7 +368,8 @@ struct FragmentCompiler { return; Spec.MountPoint = std::move(*AbsPath); Out.Apply.push_back([Spec(std::move(Spec))](const Params &P, Config &C) { - if (!P.Path.startswith(Spec.MountPoint)) + if (P.Path.empty() || !pathStartsWith(Spec.MountPoint, P.Path, + llvm::sys::path::Style::posix)) return; C.Index.External = Spec; // Disable background indexing for the files under the mountpoint. @@ -379,6 +398,8 @@ struct FragmentCompiler { for (llvm::StringRef N : Normalized) C.Diagnostics.Suppress.insert(N); }); + + compile(std::move(F.ClangTidy)); } void compile(Fragment::StyleBlock &&F) { @@ -422,7 +443,7 @@ struct FragmentCompiler { CurSpec += Str; } - void compile(Fragment::ClangTidyBlock &&F) { + void compile(Fragment::DiagnosticsBlock::ClangTidyBlock &&F) { std::string Checks; for (auto &CheckGlob : F.Add) appendTidyCheckSpec(Checks, CheckGlob, true); @@ -433,8 +454,9 @@ struct FragmentCompiler { if (!Checks.empty()) Out.Apply.push_back( [Checks = std::move(Checks)](const Params &, Config &C) { - C.ClangTidy.Checks.append( - Checks, C.ClangTidy.Checks.empty() ? /*skip comma*/ 1 : 0, + C.Diagnostics.ClangTidy.Checks.append( + Checks, + C.Diagnostics.ClangTidy.Checks.empty() ? /*skip comma*/ 1 : 0, std::string::npos); }); if (!F.CheckOptions.empty()) { @@ -445,8 +467,8 @@ struct FragmentCompiler { Out.Apply.push_back( [CheckOptions = std::move(CheckOptions)](const Params &, Config &C) { for (auto &StringPair : CheckOptions) - C.ClangTidy.CheckOptions.insert_or_assign(StringPair.first, - StringPair.second); + C.Diagnostics.ClangTidy.CheckOptions.insert_or_assign( + StringPair.first, StringPair.second); }); } } @@ -476,8 +498,8 @@ CompiledFragment Fragment::compile(DiagnosticCallback D) && { trace::Span Tracer("ConfigCompile"); SPAN_ATTACH(Tracer, "ConfigFile", ConfigFile); auto Result = std::make_shared(); - vlog("Config fragment: compiling {0}:{1} -> {2}", ConfigFile, LineCol.first, - Result.get()); + vlog("Config fragment: compiling {0}:{1} -> {2} (trusted={3})", ConfigFile, + LineCol.first, Result.get(), Source.Trusted); FragmentCompiler{*Result, D, Source.Manager.get()}.compile(std::move(*this)); // Return as cheaply-copyable wrapper. diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index 5b67c49fe1546d0a13fc1ea3690ea6752378f805..c98ca3a2dd5222eaa17e543aecf4811660783267 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -94,6 +94,9 @@ struct Fragment { /// Absolute path to directory the fragment is associated with. Relative /// paths mentioned in the fragment are resolved against this. std::string Directory; + /// Whether this fragment is allowed to make critical security/privacy + /// decisions. + bool Trusted = false; }; SourceInfo Source; @@ -203,6 +206,29 @@ struct Fragment { /// (e.g. by disabling a clang-tidy check, or the -Wunused compile flag). /// This often has other advantages, such as skipping some analysis. std::vector> Suppress; + + /// Controls how clang-tidy will run over the code base. + /// + /// The settings are merged with any settings found in .clang-tidy + /// configiration files with these ones taking precedence. + struct ClangTidyBlock { + std::vector> Add; + /// List of checks to disable. + /// Takes precedence over Add. To enable all llvm checks except include + /// order: + /// Add: llvm-* + /// Remove: llvm-include-onder + std::vector> Remove; + + /// A Key-Value pair list of options to pass to clang-tidy checks + /// These take precedence over options specified in clang-tidy + /// configuration files. Example: + /// CheckOptions: + /// readability-braces-around-statements.ShortStatementLines: 2 + std::vector, Located>> + CheckOptions; + }; + ClangTidyBlock ClangTidy; }; DiagnosticsBlock Diagnostics; @@ -215,30 +241,6 @@ struct Fragment { std::vector> FullyQualifiedNamespaces; }; StyleBlock Style; - - /// Controls how clang-tidy will run over the code base. - /// - /// The settings are merged with any settings found in .clang-tidy - /// configiration files with these ones taking precedence. - // FIXME: move this to Diagnostics.Tidy. - struct ClangTidyBlock { - std::vector> Add; - /// List of checks to disable. - /// Takes precedence over Add. To enable all llvm checks except include - /// order: - /// Add: llvm-* - /// Remove: llvm-include-onder - std::vector> Remove; - - /// A Key-Value pair list of options to pass to clang-tidy checks - /// These take precedence over options specified in clang-tidy configuration - /// files. Example: - /// CheckOptions: - /// readability-braces-around-statements.ShortStatementLines: 2 - std::vector, Located>> - CheckOptions; - }; - ClangTidyBlock ClangTidy; }; } // namespace config diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp b/clang-tools-extra/clangd/ConfigProvider.cpp index 05b2ba50566ddc7ae15138e32e08f6e24dfc2ba0..6dfb00b14fc6ccc08eaddddf581427e81d247f77 100644 --- a/clang-tools-extra/clangd/ConfigProvider.cpp +++ b/clang-tools-extra/clangd/ConfigProvider.cpp @@ -34,7 +34,7 @@ public: : FileCache(Path), Directory(Directory) {} void get(const ThreadsafeFS &TFS, DiagnosticCallback DC, - std::chrono::steady_clock::time_point FreshTime, + std::chrono::steady_clock::time_point FreshTime, bool Trusted, std::vector &Out) const { read( TFS, FreshTime, @@ -43,6 +43,7 @@ public: if (Data) for (auto &Fragment : Fragment::parseYAML(*Data, path(), DC)) { Fragment.Source.Directory = Directory; + Fragment.Source.Trusted = Trusted; CachedValue.push_back(std::move(Fragment).compile(DC)); } }, @@ -52,35 +53,38 @@ public: std::unique_ptr Provider::fromYAMLFile(llvm::StringRef AbsPath, llvm::StringRef Directory, - const ThreadsafeFS &FS) { + const ThreadsafeFS &FS, + bool Trusted) { class AbsFileProvider : public Provider { mutable FileConfigCache Cache; // threadsafe const ThreadsafeFS &FS; + bool Trusted; std::vector getFragments(const Params &P, DiagnosticCallback DC) const override { std::vector Result; - Cache.get(FS, DC, P.FreshTime, Result); + Cache.get(FS, DC, P.FreshTime, Trusted, Result); return Result; }; public: AbsFileProvider(llvm::StringRef Path, llvm::StringRef Directory, - const ThreadsafeFS &FS) - : Cache(Path, Directory), FS(FS) { + const ThreadsafeFS &FS, bool Trusted) + : Cache(Path, Directory), FS(FS), Trusted(Trusted) { assert(llvm::sys::path::is_absolute(Path)); } }; - return std::make_unique(AbsPath, Directory, FS); + return std::make_unique(AbsPath, Directory, FS, Trusted); } std::unique_ptr Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, - const ThreadsafeFS &FS) { + const ThreadsafeFS &FS, bool Trusted) { class RelFileProvider : public Provider { std::string RelPath; const ThreadsafeFS &FS; + bool Trusted; mutable std::mutex Mu; // Keys are the (posix-style) ancestor directory, not the config within it. @@ -128,18 +132,19 @@ Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, // This will take a (per-file) lock for each file that actually exists. std::vector Result; for (FileConfigCache *Cache : Caches) - Cache->get(FS, DC, P.FreshTime, Result); + Cache->get(FS, DC, P.FreshTime, Trusted, Result); return Result; }; public: - RelFileProvider(llvm::StringRef RelPath, const ThreadsafeFS &FS) - : RelPath(RelPath), FS(FS) { + RelFileProvider(llvm::StringRef RelPath, const ThreadsafeFS &FS, + bool Trusted) + : RelPath(RelPath), FS(FS), Trusted(Trusted) { assert(llvm::sys::path::is_relative(RelPath)); } }; - return std::make_unique(RelPath, FS); + return std::make_unique(RelPath, FS, Trusted); } std::unique_ptr diff --git a/clang-tools-extra/clangd/ConfigProvider.h b/clang-tools-extra/clangd/ConfigProvider.h index 25d9450f28a7214d66d3504f30aa3450fcef28ff..428438b67f14d5b1b89b28742282ccd3fd889a69 100644 --- a/clang-tools-extra/clangd/ConfigProvider.h +++ b/clang-tools-extra/clangd/ConfigProvider.h @@ -69,7 +69,8 @@ public: /// Directory will be used to resolve relative paths in the fragments. static std::unique_ptr fromYAMLFile(llvm::StringRef AbsPath, llvm::StringRef Directory, - const ThreadsafeFS &); + const ThreadsafeFS &, + bool Trusted = false); // Reads fragments from YAML files found relative to ancestors of Params.Path. // // All fragments that exist are returned, starting from distant ancestors. @@ -78,7 +79,8 @@ public: // // If Params does not specify a path, no fragments are returned. static std::unique_ptr - fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &); + fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &, + bool Trusted = false); /// A provider that includes fragments from all the supplied providers. /// Order is preserved; later providers take precedence over earlier ones. diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index 7aaff556549740d2a0671e9d0fb52d2a2a3669d8..348ee9dd1f75fae9087d068c9387616c7ab7b9e9 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -62,7 +62,7 @@ public: Dict.handle("CompileFlags", [&](Node &N) { parse(F.CompileFlags, N); }); Dict.handle("Index", [&](Node &N) { parse(F.Index, N); }); Dict.handle("Style", [&](Node &N) { parse(F.Style, N); }); - Dict.handle("ClangTidy", [&](Node &N) { parse(F.ClangTidy, N); }); + Dict.handle("Diagnostics", [&](Node &N) { parse(F.Diagnostics, N); }); Dict.parse(N); return !(N.failed() || HadError); } @@ -110,7 +110,17 @@ private: Dict.parse(N); } - void parse(Fragment::ClangTidyBlock &F, Node &N) { + void parse(Fragment::DiagnosticsBlock &F, Node &N) { + DictParser Dict("Diagnostics", this); + Dict.handle("Suppress", [&](Node &N) { + if (auto Values = scalarValues(N)) + F.Suppress = std::move(*Values); + }); + Dict.handle("ClangTidy", [&](Node &N) { parse(F.ClangTidy, N); }); + Dict.parse(N); + } + + void parse(Fragment::DiagnosticsBlock::ClangTidyBlock &F, Node &N) { DictParser Dict("ClangTidy", this); Dict.handle("Add", [&](Node &N) { if (auto Values = scalarValues(N)) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 1a5379acfe7d7d3d9a406f93d021ff0861bd561e..a38c8a57d1613dd4a18e0ab2004d69a2ffb067e6 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -395,20 +396,6 @@ DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const { return None; } -// For platforms where paths are case-insensitive (but case-preserving), -// we need to do case-insensitive comparisons and use lowercase keys. -// FIXME: Make Path a real class with desired semantics instead. -// This class is not the only place this problem exists. -// FIXME: Mac filesystems default to case-insensitive, but may be sensitive. - -static std::string maybeCaseFoldPath(PathRef Path) { -#if defined(_WIN32) || defined(__APPLE__) - return Path.lower(); -#else - return std::string(Path); -#endif -} - std::vector DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches( llvm::ArrayRef Dirs) const { @@ -567,7 +554,10 @@ public: } ~BroadcastThread() { - ShouldStop.store(true, std::memory_order_release); + { + std::lock_guard Lock(Mu); + ShouldStop.store(true, std::memory_order_release); + } CV.notify_all(); Thread.join(); } diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 403d3fe3e64f5087ba8be253dca19399e9a50aca..1020282f5ee89d6dc3a91b856d098ff58a67dbac 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -316,8 +316,8 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, Check->registerMatchers(&CTFinder); } - ASTDiags.setLevelAdjuster([&, &Cfg(Config::current())]( - DiagnosticsEngine::Level DiagLevel, + const Config& Cfg = Config::current(); + ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) { if (Cfg.Diagnostics.SuppressAll || isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress)) diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 78110dc0de603145c2c32d79dae5bda7288028c4..76cf813e6808380ae27d32bed10fbcff6060dbeb 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -27,6 +27,21 @@ namespace clang { namespace clangd { +namespace { + +// Helper that doesn't treat `null` and absent fields as failures. +template +bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop, + T &Out, llvm::json::Path P) { + auto *O = Params.getAsObject(); + assert(O); + auto *V = O->get(Prop); + // Field is missing or null. + if (!V || V->getAsNull().hasValue()) + return true; + return fromJSON(*V, Out, P.field(Prop)); +} +} // namespace char LSPError::ID; @@ -490,7 +505,7 @@ bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R, return O && O.map("textDocument", R.textDocument) && O.map("contentChanges", R.contentChanges) && O.map("wantDiagnostics", R.wantDiagnostics) && - O.mapOptional("forceRebuild", R.forceRebuild); + mapOptOrNull(Params, "forceRebuild", R.forceRebuild, P); } bool fromJSON(const llvm::json::Value &E, FileChangeType &Out, @@ -580,10 +595,10 @@ bool fromJSON(const llvm::json::Value &Params, Diagnostic &R, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); return O && O.map("range", R.range) && O.map("message", R.message) && - O.mapOptional("severity", R.severity) && - O.mapOptional("category", R.category) && - O.mapOptional("code", R.code) && O.mapOptional("source", R.source); - return true; + mapOptOrNull(Params, "severity", R.severity, P) && + mapOptOrNull(Params, "category", R.category, P) && + mapOptOrNull(Params, "code", R.code, P) && + mapOptOrNull(Params, "source", R.source, P); } llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) { @@ -818,7 +833,7 @@ bool fromJSON(const llvm::json::Value &Params, CompletionContext &R, llvm::json::ObjectMapper O(Params, P); int TriggerKind; if (!O || !O.map("triggerKind", TriggerKind) || - !O.mapOptional("triggerCharacter", R.triggerCharacter)) + !mapOptOrNull(Params, "triggerCharacter", R.triggerCharacter, P)) return false; R.triggerKind = static_cast(TriggerKind); return true; @@ -1121,8 +1136,8 @@ bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S, llvm::json::ObjectMapper O(Params, P); if (!O) return true; // 'any' type in LSP. - return O.mapOptional("compilationDatabaseChanges", - S.compilationDatabaseChanges); + return mapOptOrNull(Params, "compilationDatabaseChanges", + S.compilationDatabaseChanges, P); } bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts, @@ -1133,8 +1148,8 @@ bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts, return fromJSON(Params, Opts.ConfigSettings, P) && O.map("compilationDatabasePath", Opts.compilationDatabasePath) && - O.mapOptional("fallbackFlags", Opts.fallbackFlags) && - O.mapOptional("clangdFileStatus", Opts.FileStatus); + mapOptOrNull(Params, "fallbackFlags", Opts.fallbackFlags, P) && + mapOptOrNull(Params, "clangdFileStatus", Opts.FileStatus, P); } bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out, @@ -1190,10 +1205,11 @@ bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I, return O && O.map("name", I.name) && O.map("kind", I.kind) && O.map("uri", I.uri) && O.map("range", I.range) && O.map("selectionRange", I.selectionRange) && - O.mapOptional("detail", I.detail) && - O.mapOptional("deprecated", I.deprecated) && - O.mapOptional("parents", I.parents) && - O.mapOptional("children", I.children) && O.mapOptional("data", I.data); + mapOptOrNull(Params, "detail", I.detail, P) && + mapOptOrNull(Params, "deprecated", I.deprecated, P) && + mapOptOrNull(Params, "parents", I.parents, P) && + mapOptOrNull(Params, "children", I.children, P) && + mapOptOrNull(Params, "data", I.data, P); } bool fromJSON(const llvm::json::Value &Params, @@ -1238,7 +1254,7 @@ bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I, return O && O.map("name", I.name) && O.map("kind", I.kind) && O.map("uri", I.uri) && O.map("range", I.range) && O.map("selectionRange", I.selectionRange) && - O.mapOptional("data", I.data); + mapOptOrNull(Params, "data", I.data, P); } bool fromJSON(const llvm::json::Value &Params, diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index 0a9f12221287b2159558595d0d4a80b7d75769a0..bcf1cd5a6183a4afd75486b26c792705a5feee9c 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -106,7 +106,7 @@ public: llvm::SmallVector Caches; { std::lock_guard Lock(Mu); - for (auto I = path::begin(Parent), E = path::end(Parent); I != E; ++I) { + for (auto I = path::rbegin(Parent), E = path::rend(Parent); I != E; ++I) { assert(I->end() >= Parent.begin() && I->end() <= Parent.end() && "Canonical path components should be substrings"); llvm::StringRef Ancestor(Parent.begin(), I->end() - Parent.begin()); @@ -255,7 +255,7 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef ExtraBadChecks) { TidyProviderRef provideClangdConfig() { return [](tidy::ClangTidyOptions &Opts, llvm::StringRef) { - const auto &CurTidyConfig = Config::current().ClangTidy; + const auto &CurTidyConfig = Config::current().Diagnostics.ClangTidy; if (!CurTidyConfig.Checks.empty()) mergeCheckList(Opts.Checks, CurTidyConfig.Checks); diff --git a/clang-tools-extra/clangd/quality/CompletionModel.cmake b/clang-tools-extra/clangd/quality/CompletionModel.cmake index 60c6d2aa8433000df5ce2131d4572ba7718beb2a..dc0c0cde4dabbbd682982055303962b3522aeb0e 100644 --- a/clang-tools-extra/clangd/quality/CompletionModel.cmake +++ b/clang-tools-extra/clangd/quality/CompletionModel.cmake @@ -4,9 +4,10 @@ # ${CMAKE_CURRENT_BINARY_DIR}. The generated header # will define a C++ class called ${cpp_class} - which may be a # namespace-qualified class name. +set(CLANGD_COMPLETION_MODEL_COMPILER ${CMAKE_CURRENT_LIST_DIR}/CompletionModelCodegen.py) function(gen_decision_forest model filename cpp_class) - set(model_compiler ${CMAKE_SOURCE_DIR}/../clang-tools-extra/clangd/quality/CompletionModelCodegen.py) - + set(model_compiler ${CLANGD_COMPLETION_MODEL_COMPILER}) + set(output_dir ${CMAKE_CURRENT_BINARY_DIR}) set(header_file ${output_dir}/${filename}.h) set(cpp_file ${output_dir}/${filename}.cpp) diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index d3c7da96a441fb3c3cd0f975e93d2461820157dc..a857b347987159c0baa95aebb0f51b17d87c8c5c 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -68,7 +68,7 @@ llvm::Optional getOtherRefFile(const Decl &D, StringRef MainFile, if (OtherFile) return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { - if (*RefFilePath != MainFile) + if (!pathEqual(*RefFilePath, MainFile)) OtherFile = *RefFilePath; } }); @@ -474,7 +474,7 @@ findOccurrencesOutsideFile(const NamedDecl &RenameDecl, if ((R.Kind & RefKind::Spelled) == RefKind::Unknown) return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { - if (*RefFilePath != MainFile) + if (!pathEqual(*RefFilePath, MainFile)) AffectedFiles[*RefFilePath].push_back(toRange(R.Location)); } }); diff --git a/clang-tools-extra/clangd/support/CMakeLists.txt b/clang-tools-extra/clangd/support/CMakeLists.txt index f0fe073eb1361fb92502915fea9aa956e6c933d6..fc7d7a28117b1d507c8a621dc25b5e93e2c68b79 100644 --- a/clang-tools-extra/clangd/support/CMakeLists.txt +++ b/clang-tools-extra/clangd/support/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangdSupport Logger.cpp Markup.cpp MemoryTree.cpp + Path.cpp Shutdown.cpp Threading.cpp ThreadsafeFS.cpp diff --git a/clang-tools-extra/clangd/support/Function.h b/clang-tools-extra/clangd/support/Function.h index 2cac1b1e7f67e441963dd81d66cb29a3b19675a9..936800d5698570290c2a53de39750767425c1e1f 100644 --- a/clang-tools-extra/clangd/support/Function.h +++ b/clang-tools-extra/clangd/support/Function.h @@ -51,7 +51,7 @@ public: Subscription &operator=(Subscription &&Other) { // If *this is active, unsubscribe. if (Parent) { - std::lock_guard(Parent->ListenersMu); + std::lock_guard Lock(Parent->ListenersMu); llvm::erase_if(Parent->Listeners, [&](const std::pair &P) { return P.second == ListenerID; diff --git a/clang-tools-extra/clangd/support/Path.cpp b/clang-tools-extra/clangd/support/Path.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7907cffe60c7ea6e910fa4f94fbb7a804eaee23 --- /dev/null +++ b/clang-tools-extra/clangd/support/Path.cpp @@ -0,0 +1,39 @@ +//===--- Path.cpp -------------------------------------------*- C++-*------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/Path.h" +#include "llvm/Support/Path.h" +namespace clang { +namespace clangd { + +#ifdef CLANGD_PATH_CASE_INSENSITIVE +std::string maybeCaseFoldPath(PathRef Path) { return Path.lower(); } +bool pathEqual(PathRef A, PathRef B) { return A.equals_lower(B); } +#else // NOT CLANGD_PATH_CASE_INSENSITIVE +std::string maybeCaseFoldPath(PathRef Path) { return Path.str(); } +bool pathEqual(PathRef A, PathRef B) { return A == B; } +#endif // CLANGD_PATH_CASE_INSENSITIVE + +bool pathStartsWith(PathRef Ancestor, PathRef Path, + llvm::sys::path::Style Style) { + assert(llvm::sys::path::is_absolute(Ancestor) && + llvm::sys::path::is_absolute(Path)); + // If ancestor ends with a separator drop that, so that we can match /foo/ as + // a parent of /foo. + if (llvm::sys::path::is_separator(Ancestor.back(), Style)) + Ancestor = Ancestor.drop_back(); + // Ensure Path starts with Ancestor. + if (!pathEqual(Ancestor, Path.take_front(Ancestor.size()))) + return false; + Path = Path.drop_front(Ancestor.size()); + // Then make sure either two paths are equal or Path has a separator + // afterwards. + return Path.empty() || llvm::sys::path::is_separator(Path.front(), Style); +} +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/support/Path.h b/clang-tools-extra/clangd/support/Path.h index 4d4ad7f490473290c23004340fe3685e9425a5d6..938d7d7e99c9a64375334cd1a10cf740a96d4a67 100644 --- a/clang-tools-extra/clangd/support/Path.h +++ b/clang-tools-extra/clangd/support/Path.h @@ -10,8 +10,14 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_PATH_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Path.h" #include +/// Whether current platform treats paths case insensitively. +#if defined(_WIN32) || defined(__APPLE__) +#define CLANGD_PATH_CASE_INSENSITIVE +#endif + namespace clang { namespace clangd { @@ -22,6 +28,18 @@ using Path = std::string; /// signatures. using PathRef = llvm::StringRef; +// For platforms where paths are case-insensitive (but case-preserving), +// we need to do case-insensitive comparisons and use lowercase keys. +// FIXME: Make Path a real class with desired semantics instead. +std::string maybeCaseFoldPath(PathRef Path); +bool pathEqual(PathRef, PathRef); + +/// Checks if \p Ancestor is a proper ancestor of \p Path. This is just a +/// smarter lexical prefix match, e.g: foo/bar/baz doesn't start with foo/./bar. +/// Both \p Ancestor and \p Path must be absolute. +bool pathStartsWith( + PathRef Ancestor, PathRef Path, + llvm::sys::path::Style Style = llvm::sys::path::Style::native); } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index fe69079bfe67cd2e1f3075a6307cd823a286152b..99c3d97ce35d3c7c0f04aa50db864079790bb25c 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -831,8 +831,8 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var if (llvm::sys::path::user_config_directory(UserConfig)) { llvm::sys::path::append(UserConfig, "clangd", "config.yaml"); vlog("User config file is {0}", UserConfig); - ProviderStack.push_back( - config::Provider::fromYAMLFile(UserConfig, /*Directory=*/"", TFS)); + ProviderStack.push_back(config::Provider::fromYAMLFile( + UserConfig, /*Directory=*/"", TFS, /*Trusted=*/true)); } else { elog("Couldn't determine user config file, not loading"); } diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index adf4ac827cce349efd503305e7f027ad81e7b514..c396c6f5873b5b689769d108776d6c5b68854833 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -93,6 +93,7 @@ add_unittest(ClangdUnitTests ClangdTests TestIndex.cpp TestTU.cpp TestWorkspace.cpp + TidyProviderTests.cpp TypeHierarchyTests.cpp URITests.cpp XRefsTests.cpp @@ -103,6 +104,7 @@ add_unittest(ClangdUnitTests ClangdTests support/FunctionTests.cpp support/MarkupTests.cpp support/MemoryTreeTests.cpp + support/PathTests.cpp support/ThreadingTests.cpp support/TestTracer.cpp support/TraceTests.cpp diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index ef24b5d8417f5baa23f3b8a3b71b6cd8657c737f..a3738681bec5a3087445a5d609b1e83a581d8e9b 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -99,6 +99,25 @@ TEST_F(ConfigCompileTests, Condition) { Frag.If.PathMatch.emplace_back("ba*r"); EXPECT_FALSE(compileAndApply()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); + + // Only matches case-insensitively. + Frag = {}; + Frag.If.PathMatch.emplace_back("B.*R"); + EXPECT_THAT(Diags.Diagnostics, IsEmpty()); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + EXPECT_TRUE(compileAndApply()); +#else + EXPECT_FALSE(compileAndApply()); +#endif + + Frag = {}; + Frag.If.PathExclude.emplace_back("B.*R"); + EXPECT_THAT(Diags.Diagnostics, IsEmpty()); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + EXPECT_FALSE(compileAndApply()); +#else + EXPECT_TRUE(compileAndApply()); +#endif } TEST_F(ConfigCompileTests, CompileCommands) { @@ -259,32 +278,36 @@ TEST_F(ConfigCompileTests, DiagnosticSuppression) { } TEST_F(ConfigCompileTests, Tidy) { - Frag.ClangTidy.Add.emplace_back("bugprone-use-after-move"); - Frag.ClangTidy.Add.emplace_back("llvm-*"); - Frag.ClangTidy.Remove.emplace_back("llvm-include-order"); - Frag.ClangTidy.Remove.emplace_back("readability-*"); - Frag.ClangTidy.CheckOptions.emplace_back( + auto &Tidy = Frag.Diagnostics.ClangTidy; + Tidy.Add.emplace_back("bugprone-use-after-move"); + Tidy.Add.emplace_back("llvm-*"); + Tidy.Remove.emplace_back("llvm-include-order"); + Tidy.Remove.emplace_back("readability-*"); + Tidy.CheckOptions.emplace_back( std::make_pair(std::string("StrictMode"), std::string("true"))); - Frag.ClangTidy.CheckOptions.emplace_back(std::make_pair( + Tidy.CheckOptions.emplace_back(std::make_pair( std::string("example-check.ExampleOption"), std::string("0"))); EXPECT_TRUE(compileAndApply()); EXPECT_EQ( - Conf.ClangTidy.Checks, + Conf.Diagnostics.ClangTidy.Checks, "bugprone-use-after-move,llvm-*,-llvm-include-order,-readability-*"); - EXPECT_EQ(Conf.ClangTidy.CheckOptions.size(), 2U); - EXPECT_EQ(Conf.ClangTidy.CheckOptions.lookup("StrictMode"), "true"); - EXPECT_EQ(Conf.ClangTidy.CheckOptions.lookup("example-check.ExampleOption"), + EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.size(), 2U); + EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup("StrictMode"), + "true"); + EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup( + "example-check.ExampleOption"), "0"); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); } TEST_F(ConfigCompileTests, TidyBadChecks) { - Frag.ClangTidy.Add.emplace_back("unknown-check"); - Frag.ClangTidy.Remove.emplace_back("*"); - Frag.ClangTidy.Remove.emplace_back("llvm-includeorder"); + auto &Tidy = Frag.Diagnostics.ClangTidy; + Tidy.Add.emplace_back("unknown-check"); + Tidy.Remove.emplace_back("*"); + Tidy.Remove.emplace_back("llvm-includeorder"); EXPECT_TRUE(compileAndApply()); // Ensure bad checks are stripped from the glob. - EXPECT_EQ(Conf.ClangTidy.Checks, "-*"); + EXPECT_EQ(Conf.Diagnostics.ClangTidy.Checks, "-*"); EXPECT_THAT( Diags.Diagnostics, ElementsAre( @@ -295,21 +318,35 @@ TEST_F(ConfigCompileTests, TidyBadChecks) { DiagKind(llvm::SourceMgr::DK_Warning)))); } +TEST_F(ConfigCompileTests, ExternalServerNeedsTrusted) { + Fragment::IndexBlock::ExternalBlock External; + External.Server.emplace("xxx"); + Frag.Index.External = std::move(External); + compileAndApply(); + EXPECT_THAT( + Diags.Diagnostics, + ElementsAre(DiagMessage( + "Remote index may not be specified by untrusted configuration. " + "Copy this into user config to use it."))); + EXPECT_FALSE(Conf.Index.External.hasValue()); +} + TEST_F(ConfigCompileTests, ExternalBlockWarnOnMultipleSource) { + Frag.Source.Trusted = true; Fragment::IndexBlock::ExternalBlock External; External.File.emplace(""); External.Server.emplace(""); Frag.Index.External = std::move(External); compileAndApply(); - llvm::StringLiteral ExpectedDiag = #ifdef CLANGD_ENABLE_REMOTE - "Exactly one of File or Server must be set."; + EXPECT_THAT( + Diags.Diagnostics, + Contains(AllOf(DiagMessage("Exactly one of File or Server must be set."), + DiagKind(llvm::SourceMgr::DK_Error)))); #else - "Clangd isn't compiled with remote index support, ignoring Server."; + ASSERT_TRUE(Conf.Index.External.hasValue()); + EXPECT_EQ(Conf.Index.External->Kind, Config::ExternalIndexSpec::File); #endif - EXPECT_THAT(Diags.Diagnostics, - Contains(AllOf(DiagMessage(ExpectedDiag), - DiagKind(llvm::SourceMgr::DK_Error)))); } TEST_F(ConfigCompileTests, ExternalBlockErrOnNoSource) { @@ -402,6 +439,23 @@ TEST_F(ConfigCompileTests, ExternalBlockMountPoint) { ASSERT_THAT(Diags.Diagnostics, IsEmpty()); ASSERT_TRUE(Conf.Index.External); EXPECT_THAT(Conf.Index.External->MountPoint, FooPath); + + // Only matches case-insensitively. + BazPath = testPath("fOo/baz.h", llvm::sys::path::Style::posix); + BazPath = llvm::sys::path::convert_to_slash(BazPath); + Parm.Path = BazPath; + + FooPath = testPath("FOO/", llvm::sys::path::Style::posix); + FooPath = llvm::sys::path::convert_to_slash(FooPath); + Frag = GetFrag("", FooPath.c_str()); + compileAndApply(); + ASSERT_THAT(Diags.Diagnostics, IsEmpty()); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + ASSERT_TRUE(Conf.Index.External); + EXPECT_THAT(Conf.Index.External->MountPoint, FooPath); +#else + ASSERT_FALSE(Conf.Index.External); +#endif } } // namespace } // namespace config diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp index 25d468ba604ab8ef61d1f204be7ab0e3e8e76381..e1c81344de201cfa0c8e4ef1666d8a67647d7860 100644 --- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp @@ -60,10 +60,11 @@ CompileFlags: Index: Background: Skip --- -ClangTidy: - CheckOptions: - IgnoreMacros: true - example-check.ExampleOption: 0 +Diagnostics: + ClangTidy: + CheckOptions: + IgnoreMacros: true + example-check.ExampleOption: 0 )yaml"; auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); @@ -77,7 +78,7 @@ ClangTidy: ASSERT_TRUE(Results[2].Index.Background); EXPECT_EQ("Skip", *Results[2].Index.Background.getValue()); - EXPECT_THAT(Results[3].ClangTidy.CheckOptions, + EXPECT_THAT(Results[3].Diagnostics.ClangTidy.CheckOptions, ElementsAre(PairVal("IgnoreMacros", "true"), PairVal("example-check.ExampleOption", "0"))); } diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp index 4bc03796bb2baa5475ae311fc3a743675a9df09f..b2c83a1a430387bc8af590ca596c1492b9f69692 100644 --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -1067,6 +1067,52 @@ TEST(RenameTest, Renameable) { } } +MATCHER_P(newText, T, "") { return arg.newText == T; } + +TEST(RenameTest, IndexMergeMainFile) { + Annotations Code("int ^x();"); + TestTU TU = TestTU::withCode(Code.code()); + TU.Filename = "main.cc"; + auto AST = TU.build(); + + auto Main = testPath("main.cc"); + + auto Rename = [&](const SymbolIndex *Idx) { + auto GetDirtyBuffer = [&](PathRef Path) -> llvm::Optional { + return Code.code().str(); // Every file has the same content. + }; + RenameOptions Opts; + Opts.AllowCrossFile = true; + RenameInputs Inputs{Code.point(), "xPrime", AST, Main, + Idx, Opts, GetDirtyBuffer}; + auto Results = rename(Inputs); + EXPECT_TRUE(bool(Results)) << llvm::toString(Results.takeError()); + return std::move(*Results); + }; + + // We do not expect to see duplicated edits from AST vs index. + auto Results = Rename(TU.index().get()); + EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main)); + EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(), + ElementsAre(newText("xPrime"))); + + // Sanity check: we do expect to see index results! + TU.Filename = "other.cc"; + Results = Rename(TU.index().get()); + EXPECT_THAT(Results.GlobalChanges.keys(), + UnorderedElementsAre(Main, testPath("other.cc"))); + +#ifdef CLANGD_PATH_CASE_INSENSITIVE + // On case-insensitive systems, no duplicates if AST vs index case differs. + // https://github.com/clangd/clangd/issues/665 + TU.Filename = "MAIN.CC"; + Results = Rename(TU.index().get()); + EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main)); + EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(), + ElementsAre(newText("xPrime"))); +#endif +} + TEST(RenameTest, MainFileReferencesOnly) { // filter out references not from main file. llvm::StringRef Test = diff --git a/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp b/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a16c87456a1a0e0906c219809e463771354e0852 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp @@ -0,0 +1,60 @@ +//===-- TidyProviderTests.cpp - Clang tidy configuration provider tests ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestFS.h" +#include "TidyProvider.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { + +namespace { + +TEST(TidyProvider, NestedDirectories) { + MockFS FS; + FS.Files[testPath(".clang-tidy")] = R"yaml( + Checks: 'llvm-*' + CheckOptions: + - key: TestKey + value: 1 +)yaml"; + FS.Files[testPath("sub1/.clang-tidy")] = R"yaml( + Checks: 'misc-*' + CheckOptions: + - key: TestKey + value: 2 +)yaml"; + FS.Files[testPath("sub1/sub2/.clang-tidy")] = R"yaml( + Checks: 'bugprone-*' + CheckOptions: + - key: TestKey + value: 3 + InheritParentConfig: true +)yaml"; + + TidyProvider Provider = provideClangTidyFiles(FS); + + auto BaseOptions = getTidyOptionsForFile(Provider, testPath("File.cpp")); + ASSERT_TRUE(BaseOptions.Checks.hasValue()); + EXPECT_EQ(*BaseOptions.Checks, "llvm-*"); + EXPECT_EQ(BaseOptions.CheckOptions.lookup("TestKey").Value, "1"); + + auto Sub1Options = getTidyOptionsForFile(Provider, testPath("sub1/File.cpp")); + ASSERT_TRUE(Sub1Options.Checks.hasValue()); + EXPECT_EQ(*Sub1Options.Checks, "misc-*"); + EXPECT_EQ(Sub1Options.CheckOptions.lookup("TestKey").Value, "2"); + + auto Sub2Options = + getTidyOptionsForFile(Provider, testPath("sub1/sub2/File.cpp")); + ASSERT_TRUE(Sub2Options.Checks.hasValue()); + EXPECT_EQ(*Sub2Options.Checks, "misc-*,bugprone-*"); + EXPECT_EQ(Sub2Options.CheckOptions.lookup("TestKey").Value, "3"); +} +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/support/PathTests.cpp b/clang-tools-extra/clangd/unittests/support/PathTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..599c76926d30de20058153402e40ea78ad39003c --- /dev/null +++ b/clang-tools-extra/clangd/unittests/support/PathTests.cpp @@ -0,0 +1,37 @@ +//===-- PathTests.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestFS.h" +#include "support/Path.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { +TEST(PathTests, IsAncestor) { + EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("foo"))); + EXPECT_TRUE(pathStartsWith(testPath("foo/"), testPath("foo"))); + + EXPECT_FALSE(pathStartsWith(testPath("foo"), testPath("fooz"))); + EXPECT_FALSE(pathStartsWith(testPath("foo/"), testPath("fooz"))); + + EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("foo/bar"))); + EXPECT_TRUE(pathStartsWith(testPath("foo/"), testPath("foo/bar"))); + +#ifdef CLANGD_PATH_CASE_INSENSITIVE + EXPECT_TRUE(pathStartsWith(testPath("fOo"), testPath("foo/bar"))); + EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("fOo/bar"))); +#else + EXPECT_FALSE(pathStartsWith(testPath("fOo"), testPath("foo/bar"))); + EXPECT_FALSE(pathStartsWith(testPath("foo"), testPath("fOo/bar"))); +#endif +} +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 2960aad5a5569a538aed16eaf2d222f484804d5c..29321bb3eb04c502b868a28a81b1f8c4ea18dcd7 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -47,6 +47,9 @@ Major New Features Improvements to clangd ---------------------- +Performance +^^^^^^^^^^^ + - clangd's memory usage is significantly reduced on most Linux systems. In particular, memory usage should not increase dramatically over time. @@ -59,6 +62,172 @@ Improvements to clangd systems can disable this using ``--malloc_trim=0`` or the CMake flag ``-DCLANGD_MALLOC_TRIM=0``. +- Added the `$/memoryUsage request + `_: an LSP extension. + This provides a breakdown of the memory clangd thinks it is using (excluding + malloc overhead etc). The clangd VSCode extension supports showing the memory + usage tree. + +Parsing and selection +^^^^^^^^^^^^^^^^^^^^^ + +- Improved navigation of broken code in C using Recovery AST. (This has been + enabled for C++ since clangd 11). + +- Types are understood more often in broken code. (This is the first release + where Recovery AST preserves speculated types). + +- Heuristic resolution for dependent names in templates. + +Code completion +^^^^^^^^^^^^^^^ + +- Higher priority for symbols that were already used in this file, and symbols + from namespaces mentioned in this file. (Estimated 3% accuracy improvement) + +- Introduced a ranking algorithm trained on snippets from a large C++ codebase. + Use the flag ``--ranking-model=decision_forest`` to try this (Estimated 6% + accuracy improvement). This mode is likely to become the default in future. + + Note: this is a generic model, not specialized for your code. clangd does not + collect any data from your code to train code completion. + +- Signature help works with functions with template-dependent parameter types. + +Go to definition +^^^^^^^^^^^^^^^^ + +- Selecting an ``auto`` or ``decltype`` keyword will attempt to navigate to + a definition of the deduced type. + +- Improved handling of aliases: navigate to the underlying entity more often. + +- Better understanding of declaration vs definition for Objective-C classes and + protocols. + +- Selecting a pure-virtual method shows its overrides. + +Find references +^^^^^^^^^^^^^^^ + +- Indexes are smarter about not returning stale references when code is deleted. + +- References in implementation files are always indexed, so results should be + more complete. + +- Find-references on a virtual method shows references to overridden methods. + +New navigation features +^^^^^^^^^^^^^^^^^^^^^^^ + +- Call hierarchy (``textDocument/callHierarchy``) is supported. + Only incoming calls are available. + +- Go to implementation (``textDocument/implementation``) is supported on + abstract classes, and on virtual methods. + +- Symbol search (``workspace/symbol``) queries may be partially qualified. + That is, typing ``b::Foo`` will match the symbol ``a::b::c::Foo``. + +Refactoring +^^^^^^^^^^^ + +- New refactoring: populate ``switch`` statement with cases. + (This acts as a fix for the ``-Wswitch-enum`` warning). + +- Renaming templates is supported, and many other complex cases were fixed. + +- Attempting to rename to an invalid or conflicting name can produce an error + message rather than broken code. (Not all cases are detected!) + +- The accuracy of many code actions has been improved. + +Hover +^^^^^ + +- Hovers for ``auto`` and ``decltype`` show the type in the same style as other + hovers. ``this`` is also now supported. + +- Displayed type names are more consistent and idiomatic. + +Semantic highlighting +^^^^^^^^^^^^^^^^^^^^^ + +- Inactive preprocessor regions (``#ifdef``) are highlighted as comments. + +- clangd 12 is the last release with support for the non-standard + ``textDocument/semanticHighlights`` notification. Clients sholud migrate to + the ``textDocument/semanticTokens`` request added in LSP 3.16. + +Remote index (alpha) +^^^^^^^^^^^^^^^^^^^^ + +- clangd can now connect to a remote index server instead of building a project + index locally. This saves resources in large codebases that are slow to index. + +- The server program is ``clangd-index-server``, and it consumes index files + produced by ``clangd-indexer``. + +- This feature requires clangd to be built with the CMake flag + ``-DCLANGD_ENABLE_REMOTE=On``, which requires GRPC libraries and is not + enabled by default. Unofficial releases of the remote-index-enabled client + and server tools are at https://github.com/clangd/clangd/releases + +- Large projects can deploy a shared server, and check in a ``.clangd`` file + to enable it (in the ``Index.External`` section). We hope to provide such a + server for ``llvm-project`` itself in the near future. + +Configuration +^^^^^^^^^^^^^ + +- Static and remote indexes can be configured in the ``Index.External`` section. + Different static indexes can now be used for different files. + (Obsoletes the flag ``--index-file``). + +- Diagnostics can be filtered or suppressed in the ``Diagnostics`` section. + +- Clang-tidy checks can be enabled/disabled in the ``Diagnostics.ClangTidy`` + section. (Obsoletes the flag ``--clang-tidy-checks``). + +- The compilation database directory can be configured in the ``CompileFlags`` + section. Different compilation databases can now be specified for different + files. (Obsoletes the flag ``--compile-commands-dir``). + +- Errors in loaded configuration files are published as LSP diagnostics, and so + should be shown in your editor. + +`Full reference of configuration options `_ + +System integration +^^^^^^^^^^^^^^^^^^ + +- Changes to ``compile_commands.json`` and ``compile_flags.txt`` will take + effect the next time a file is parsed, without restarting clangd. + +- ``clangd --check=`` can be run on the command-line to simulate + opening a file without actually using an editor. This can be useful to + reproduce crashes or aother problems. + +- Various fixes to handle filenames correctly (and case-insensitively) on + windows. + +- If incoming LSP messages are malformed, the logs now contain details. + +Miscellaneous +^^^^^^^^^^^^^ + +- "Show AST" request + (`textDocument/ast `_) + added as an LSP extension. This displays a simplified view of the clang AST + for selected code. The clangd VSCode extension supports this. + +- clangd should no longer crash while loading old or corrupt index files. + +- The flags ``--index``, ``--recovery-ast`` and ``-suggest-missing-includes`` + have been retired. These features are now always enabled. + +- Too many stability and correctness fixes to mention. + Improvements to clang-doc ------------------------- @@ -121,12 +290,6 @@ New checks Finds structs that are inefficiently packed or aligned, and recommends packing and/or aligning of said structs as needed. -- New :doc:`cppcoreguidelines-prefer-member-initializer - ` check. - - Finds member initializations in the constructor body which can be placed into - the initialization list instead. - - New :doc:`bugprone-misplaced-pointer-arithmetic-in-alloc ` check. @@ -195,6 +358,16 @@ Changes in existing checks Added `std::basic_string_view` to default list of ``string``-like types. +Deprecated checks +^^^^^^^^^^^^^^^^^ + +- The :doc:`readability-deleted-default + ` check has been deprecated. + + The clang warning `Wdefaulted-function-deleted + `_ + will diagnose the same issues and is enabled by default. + Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst deleted file mode 100644 index 5a5ee3e57a8cb299d432c626d97422ecf594d806..0000000000000000000000000000000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. title:: clang-tidy - cppcoreguidelines-prefer-member-initializer - -cppcoreguidelines-prefer-member-initializer -=========================================== - -Finds member initializations in the constructor body which can be converted -into member initializers of the constructor instead. This not only improves -the readability of the code but also positively affects its performance. -Class-member assignments inside a control statement or following the first -control statement are ignored. - -This check implements `C.49 `_ from the CppCoreGuidelines. - -If the language version is `C++ 11` or above, the constructor is the default -constructor of the class, the field is not a bitfield (only in case of earlier -language version than `C++ 20`), furthermore the assigned value is a literal, -negated literal or ``enum`` constant then the preferred place of the -initialization is at the class member declaration. - -This latter rule is `C.48 `_ from CppCoreGuidelines. - -Please note, that this check does not enforce this latter rule for -initializations already implemented as member initializers. For that purpose -see check `modernize-use-default-member-init `_. - -Example 1 ---------- - -.. code-block:: c++ - - class C { - int n; - int m; - public: - C() { - n = 1; // Literal in default constructor - if (dice()) - return; - m = 1; - } - }; - -Here ``n`` can be initialized using a default member initializer, unlike -``m``, as ``m``'s initialization follows a control statement (``if``): - -.. code-block:: c++ - - class C { - int n{1}; - int m; - public: - C() { - if (dice()) - return; - m = 1; - } - -Example 2 ---------- - -.. code-block:: c++ - - class C { - int n; - int m; - public: - C(int nn, int mm) { - n = nn; // Neither default constructor nor literal - if (dice()) - return; - m = mm; - } - }; - -Here ``n`` can be initialized in the constructor initialization list, unlike -``m``, as ``m``'s initialization follows a control statement (``if``): - -.. code-block:: c++ - - C(int nn, int mm) : n(nn) { - if (dice()) - return; - m = mm; - } - -.. option:: UseAssignment - - If this option is set to `true` (default is `false`), the check will initialize - members with an assignment. In this case the fix of the first example looks - like this: - -.. code-block:: c++ - - class C { - int n = 1; - int m; - public: - C() { - if (dice()) - return; - m = 1; - } - }; diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst index 00134eb05484ce4c1862f5c23c805a370670061d..5f2083e00061aabaa7fb3837dd2f1c296c5febb0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst @@ -3,20 +3,6 @@ readability-deleted-default =========================== -Checks that constructors and assignment operators marked as ``= default`` are -not actually deleted by the compiler. - -.. code-block:: c++ - - class Example { - public: - // This constructor is deleted because I is missing a default value. - Example() = default; - // This is fine. - Example(const Example& Other) = default; - // This operator is deleted because I cannot be assigned (it is const). - Example& operator=(const Example& Other) = default; - - private: - const int I; - }; +This check has been deprecated prefer to make use of the `Wdefaulted-function-deleted +`_ +flag. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp deleted file mode 100644 index dc6cb7606a0ded669090812aff4076970ab08d62..0000000000000000000000000000000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer,modernize-use-default-member-init %t -- \ -// RUN: -config="{CheckOptions: [{key: modernize-use-default-member-init.UseAssignment, value: 1}]}" - -class Simple1 { - int n; - // CHECK-FIXES: int n = 0; - double x; - // CHECK-FIXES: double x = 0.0; - -public: - Simple1() { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple1(int nn, double xx) { - // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple1() = default; -}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp deleted file mode 100644 index fe5bb7c3bb989ea12863dfe709825f224707813f..0000000000000000000000000000000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer,modernize-use-default-member-init %t - -class Simple1 { - int n; - // CHECK-FIXES: int n{0}; - double x; - // CHECK-FIXES: double x{0.0}; - -public: - Simple1() { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple1(int nn, double xx) { - // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple1() = default; -}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp deleted file mode 100644 index b5c04c32c9fad6982eddaad04330fb0b8ea1fe89..0000000000000000000000000000000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer %t -- -- -fcxx-exceptions - -extern void __assert_fail (__const char *__assertion, __const char *__file, - unsigned int __line, __const char *__function) - __attribute__ ((__noreturn__)); -#define assert(expr) \ - ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) - -class Simple1 { - int n; - double x; - -public: - Simple1() { - // CHECK-FIXES: Simple1() : n(0), x(0.0) { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple1(int nn, double xx) { - // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple1() = default; -}; - -class Simple2 { - int n; - double x; - -public: - Simple2() : n(0) { - // CHECK-FIXES: Simple2() : n(0), x(0.0) { - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple2(int nn, double xx) : n(nn) { - // CHECK-FIXES: Simple2(int nn, double xx) : n(nn), x(xx) { - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple2() = default; -}; - -class Simple3 { - int n; - double x; - -public: - Simple3() : x(0.0) { - // CHECK-FIXES: Simple3() : n(0), x(0.0) { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple3(int nn, double xx) : x(xx) { - // CHECK-FIXES: Simple3(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple3() = default; -}; - -int something_int(); -double something_double(); - -class Simple4 { - int n; - -public: - Simple4() { - // CHECK-FIXES: Simple4() : n(something_int()) { - n = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple4() = default; -}; - -static bool dice(); - -class Complex1 { - int n; - int m; - -public: - Complex1() : n(0) { - if (dice()) - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional expression - } - - ~Complex1() = default; -}; - -class Complex2 { - int n; - int m; - -public: - Complex2() : n(0) { - if (!dice()) - return; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional expression - } - - ~Complex2() = default; -}; - -class Complex3 { - int n; - int m; - -public: - Complex3() : n(0) { - while (dice()) - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional loop - } - - ~Complex3() = default; -}; - -class Complex4 { - int n; - int m; - -public: - Complex4() : n(0) { - while (!dice()) - return; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional loop - } - - ~Complex4() = default; -}; - -class Complex5 { - int n; - int m; - -public: - Complex5() : n(0) { - do { - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional loop - } while (dice()); - } - - ~Complex5() = default; -}; - -class Complex6 { - int n; - int m; - -public: - Complex6() : n(0) { - do { - return; - } while (!dice()); - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional loop - } - - ~Complex6() = default; -}; - -class Complex7 { - int n; - int m; - -public: - Complex7() : n(0) { - for (int i = 2; i < 1; ++i) { - m = 1; - } - // NO-MESSAGES: initialization of 'm' is nested into a conditional loop - } - - ~Complex7() = default; -}; - -class Complex8 { - int n; - int m; - -public: - Complex8() : n(0) { - for (int i = 0; i < 2; ++i) { - return; - } - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional loop - } - - ~Complex8() = default; -}; - -class Complex9 { - int n; - int m; - -public: - Complex9() : n(0) { - switch (dice()) { - case 1: - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional expression - break; - default: - break; - } - } - - ~Complex9() = default; -}; - -class Complex10 { - int n; - int m; - -public: - Complex10() : n(0) { - switch (dice()) { - case 1: - return; - break; - default: - break; - } - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional expression - } - - ~Complex10() = default; -}; - -class E {}; -int risky(); // may throw - -class Complex11 { - int n; - int m; - -public: - Complex11() : n(0) { - try { - risky(); - m = 1; - // NO-MESSAGES: initialization of 'm' follows is nested in a try-block - } catch (const E& e) { - return; - } - } - - ~Complex11() = default; -}; - -class Complex12 { - int n; - int m; - -public: - Complex12() : n(0) { - try { - risky(); - } catch (const E& e) { - return; - } - m = 1; - // NO-MESSAGES: initialization of 'm' follows a try-block - } - - ~Complex12() = default; -}; - -class Complex13 { - int n; - int m; - -public: - Complex13() : n(0) { - return; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a return statement - } - - ~Complex13() = default; -}; - -class Complex14 { - int n; - int m; - -public: - Complex14() : n(0) { - goto X; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a goto statement - X: - ; - } - - ~Complex14() = default; -}; - -void returning(); - -class Complex15 { - int n; - int m; - -public: - Complex15() : n(0) { - // CHECK-FIXES: Complex15() : n(0), m(1) { - returning(); - m = 1; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Complex15() = default; -}; - -[[noreturn]] void not_returning(); - -class Complex16 { - int n; - int m; - -public: - Complex16() : n(0) { - not_returning(); - m = 1; - // NO-MESSAGES: initialization of 'm' follows a non-returning function call - } - - ~Complex16() = default; -}; - -class Complex17 { - int n; - int m; - -public: - Complex17() : n(0) { - throw 1; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a 'throw' statement; - } - - ~Complex17() = default; -}; - -class Complex18 { - int n; - -public: - Complex18() try { - n = risky(); - // NO-MESSAGES: initialization of 'n' in a 'try' body; - } catch (const E& e) { - n = 0; - } - - ~Complex18() = default; -}; - -class Complex19 { - int n; -public: - Complex19() { - // CHECK-FIXES: Complex19() : n(0) { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - explicit Complex19(int) { - // CHECK-FIXES: Complex19(int) : n(12) { - n = 12; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Complex19() = default; -}; - -class Complex20 { - int n; - int m; - -public: - Complex20(int k) : n(0) { - assert(k > 0); - m = 1; - // NO-MESSAGES: initialization of 'm' follows an assertion - } - - ~Complex20() = default; -}; - -class VeryComplex1 { - int n1, n2, n3; - double x1, x2, x3; - int n4, n5, n6; - double x4, x5, x6; - - VeryComplex1() : n3(something_int()), x3(something_double()), - n5(something_int()), x4(something_double()), - x5(something_double()) { - // CHECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()), - // CHECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()), - // CHECK-FIXES: x5(something_double()), x6(something_double()) { - -// FIXME: Order of elements on the constructor initializer list should match -// the order of the declaration of the fields. Thus the correct fixes -// should look like these: -// - // C ECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()), - // C ECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()), - // C ECK-FIXES: x5(something_double()), x6(something_double()) { -// -// However, the Diagnostics Engine processes fixes in the order of the -// diagnostics and insertions to the same position are handled in left to -// right order thus in the case two adjacent fields are initialized -// inside the constructor in reverse order the provided fix is a -// constructor initializer list that does not match the order of the -// declaration of the fields. - - x2 = something_double(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n2 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x6 = something_double(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x1 = something_double(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n6 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n1 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n4 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n4' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } -}; - -struct Outside { - int n; - double x; - Outside(); -}; - -Outside::Outside() { - // CHECK-FIXES: Outside::Outside() : n(1), x(1.0) { - n = 1; - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 1.0; - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} -} diff --git a/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt b/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt index be35b71d15cfee2873a37b06b03bf0bbc4271af9..05d330dd8033bfd246ba01056feaed32401e05f9 100644 --- a/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt +++ b/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt @@ -1,7 +1,6 @@ set(LLVM_LINK_COMPONENTS FrontendOpenMP Support - TestingSupport ) get_filename_component(CLANG_LINT_SOURCE_DIR @@ -46,4 +45,5 @@ target_link_libraries(ClangTidyTests clangTidyObjCModule clangTidyReadabilityModule clangTidyUtils + LLVMTestingSupport ) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3001d6feb6317b8176dcb150eb980363eca9ada9..460a62734e9065f30514c1cb56611c9c060876c7 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -73,31 +73,15 @@ New Compiler Flags - ... -- -fpch-codegen and -fpch-debuginfo generate shared code and/or debuginfo - for contents of a precompiled header in a separate object file. This object - file needs to be linked in, but its contents do not need to be generated - for other objects using the precompiled header. This should usually save - compile time. If not using clang-cl, the separate object file needs to - be created explicitly from the precompiled header. - Example of use: - - .. code-block:: console - - $ clang++ -x c++-header header.h -o header.pch -fpch-codegen -fpch-debuginfo - $ clang++ -c header.pch -o shared.o - $ clang++ -c source.cpp -o source.o -include-pch header.pch - $ clang++ -o binary source.o shared.o - - - Using -fpch-instantiate-templates when generating the precompiled header - usually increases the amount of code/debuginfo that can be shared. - - In some cases, especially when building with optimizations enabled, using - -fpch-codegen may generate so much code in the shared object that compiling - it may be a net loss in build time. - - Since headers may bring in private symbols of other libraries, it may be - sometimes necessary to discard unused symbols (such as by adding - -Wl,--gc-sections on ELF platforms to the linking command, and possibly - adding -fdata-sections -ffunction-sections to the command generating - the shared object). +- AArch64 options ``-moutline-atomics``, ``-mno-outline-atomics`` to enable + and disable calls to helper functions implementing atomic operations. These + out-of-line helpers like '__aarch64_cas8_relax' will detect at runtime + AArch64 Large System Extensions (LSE) availability and either use their + atomic instructions, or falls back to LL/SC loop. These options do not apply + if the compilation target supports LSE. Atomic instructions are used directly + in that case. The option's behaviour mirrors GCC, the helpers are implemented + both in compiler-rt and libgcc. + - New option ``-fbinutils-version=`` specifies the targeted binutils version. For example, ``-fbinutils-version=2.35`` means compatibility with GNU as/ld before 2.35 is not needed: new features can be used and there is no need to @@ -109,6 +93,10 @@ Deprecated Compiler Flags The following options are deprecated and ignored. They will be removed in future versions of Clang. +- The clang-cl ``/fallback`` flag, which made clang-cl invoke Microsoft Visual + C++ on files it couldn't compile itself, has been deprecated. It will be + removed in Clang 13. + - ... Modified Compiler Flags @@ -126,6 +114,16 @@ Modified Compiler Flags This behavior matches newer GCC. (`D91760 `_) (`D92054 `_) +- Support has been added for the following processors (command-line identifiers + in parentheses): + + - Arm Cortex-A78C (cortex-a78c). + - Arm Cortex-R82 (cortex-r82). + - Arm Neoverse V1 (neoverse-v1). + - Arm Neoverse N2 (neoverse-n2). + - Fujitsu A64FX (a64fx). + For example, to select architecture support and tuning for Neoverse-V1 based + systems, use ``-mcpu=neoverse-v1``. Removed Compiler Flags ------------------------- @@ -140,6 +138,18 @@ New Pragmas in Clang - ... +Modified Pragmas in Clang +------------------------- + +- The "#pragma clang loop vectorize_width" has been extended to support an + optional 'fixed|scalable' argument, which can be used to indicate that the + compiler should use fixed-width or scalable vectorization. Fixed-width is + assumed by default. + + Scalable or vector length agnostic vectorization is an experimental feature + for targets that support scalable vectors. For more information please refer + to the Clang Language Extensions documentation. + Attribute Changes in Clang -------------------------- @@ -150,6 +160,21 @@ Attribute Changes in Clang Windows Support --------------- +- Implicitly add ``.exe`` suffix for MinGW targets, even when cross compiling. + (This matches a change from GCC 8.) + +- Windows on Arm64: programs using the C standard library's setjmp and longjmp + functions may crash with a "Security check failure or stack buffer overrun" + exception. To workaround (with reduced security), compile with + /guard:cf,nolongjmp. + +- Windows on Arm64: LLVM 12 adds official binary release hosted on + Windows on Arm64. The binary is built and tested by Linaro alongside + AArch64 and ARM 32-bit Linux binary releases. This first WoA release + includes Clang compiler, LLD Linker, and compiler-rt runtime libraries. + Work on LLDB, sanitizer support, OpenMP, and other features is in progress + and will be included in future Windows on Arm64 LLVM releases. + C Language Changes in Clang --------------------------- @@ -167,10 +192,38 @@ C++1z Feature Support Objective-C Language Changes in Clang ------------------------------------- -OpenCL C Language Changes in Clang ----------------------------------- - -... +OpenCL Kernel Language Changes in Clang +--------------------------------------- + +- Improved online documentation: :doc:`UsersManual` and :doc:`OpenCLSupport` + pages. +- Added ``-cl-std=CL3.0`` and predefined version macro for OpenCL 3.0. +- Added ``-cl-std=CL1.0`` and mapped to the existing OpenCL 1.0 functionality. +- Improved OpenCL extension handling per target. +- Added clang extension for function pointers ``__cl_clang_function_pointers`` + and variadic functions ``__cl_clang_variadic_functions``, more details can be + found in :doc:`LanguageExtensions`. +- Removed extensions without kernel language changes: + ``cl_khr_select_fprounding_mode``, ``cl_khr_gl_sharing``, ``cl_khr_icd``, + ``cl_khr_gl_event``, ``cl_khr_d3d10_sharing``, ``cl_khr_context_abort``, + ``cl_khr_d3d11_sharing``, ``cl_khr_dx9_media_sharing``, + ``cl_khr_image2d_from_buffer``, ``cl_khr_initialize_memory``, + ``cl_khr_gl_depth_images``, ``cl_khr_spir``, ``cl_khr_egl_event``, + ``cl_khr_egl_image``, ``cl_khr_terminate_context``. +- Improved diagnostics for unevaluated ``vec_step`` expression. +- Allow nested pointers (e.g. pointer-to-pointer) kernel arguments beyond OpenCL + 1.2. +- Added ``global_device`` and ``global_host`` address spaces for USM + allocations. + +Miscellaneous improvements in C++ for OpenCL support: + +- Added diagnostics for pointers to member functions and references to + functions. +- Added support of ``vec_step`` builtin. +- Fixed ICE on address spaces with forwarding references and templated copy + constructors. +- Removed warning for variadic macro use. ABI Changes in Clang -------------------- @@ -247,15 +300,41 @@ release of Clang. Users of the build system should adjust accordingly. AST Matchers ------------ -- The behavior of TK_IgnoreUnlessSpelledInSource with the traverse() matcher - has been changed to no longer match on template instantiations or on +- The ``mapAnyOf()`` matcher was added. This allows convenient matching of + different AST nodes which have a compatible matcher API. For example, + ``mapAnyOf(ifStmt, forStmt).with(hasCondition(integerLiteral()))`` + matches any ``IfStmt`` or ``ForStmt`` with a integer literal as the + condition. + +- The ``binaryOperation()`` matcher allows matching expressions which + appear like binary operators in the code, even if they are really + ``CXXOperatorCallExpr`` for example. It is based on the ``mapAnyOf()`` + matcher functionality. The matcher API for the latter node has been + extended with ``hasLHS()`` etc to facilitate the abstraction. + +- Matcher API for ``CXXRewrittenBinaryOperator`` has been added. In addition + to explicit matching with the ``cxxRewrittenBinaryOperator()`` matcher, the + ``binaryOperation()`` matches on nodes of this type. + +- The behavior of ``TK_IgnoreUnlessSpelledInSource`` with the ``traverse()`` + matcher has been changed to no longer match on template instantiations or on implicit nodes which are not spelled in the source. -- The TK_IgnoreImplicitCastsAndParentheses traversal kind was removed. It - is recommended to use TK_IgnoreUnlessSpelledInSource instead. +- The ``TK_IgnoreImplicitCastsAndParentheses`` traversal kind was removed. It + is recommended to use ``TK_IgnoreUnlessSpelledInSource`` instead. -- The behavior of the forEach() matcher was changed to not internally ignore - implicit and parenthesis nodes. +- The behavior of the ``forEach()`` matcher was changed to not internally + ignore implicit and parenthesis nodes. This makes it consistent with + the ``has()`` matcher. Uses of ``forEach()`` relying on the old behavior + can now use the ``traverse()`` matcher or ``ignoringParenCasts()``. + +- Several AST Matchers have been changed to match based on the active + traversal mode. For example, ``argumentCountIs()`` matches the number of + arguments written in the source, ignoring default arguments represented + by ``CXXDefaultArgExpr`` nodes. + +- Improvements in AST Matchers allow more matching of template declarations, + independent of their template instantations. clang-format ------------ @@ -310,6 +389,9 @@ clang-format ``AlignConsecutiveDeclarations`` and ``AlignConsecutiveMacros`` have been modified to allow alignment across empty lines and/or comments. +- Support for Whitesmiths has been improved, with fixes for ``namespace`` blocks + and ``case`` blocks and labels. + libclang -------- @@ -318,7 +400,38 @@ libclang Static Analyzer --------------- -- ... +.. 3ff220de9009 [analyzer][StdLibraryFunctionsChecker] Add POSIX networking functions +.. ...And a million other patches. +- Improve the analyzer's understanding of several POSIX functions. + +.. https://reviews.llvm.org/D86533#2238207 +- Greatly improved the analyzer’s constraint solver by better understanding + when constraints are imposed on multiple symbolic values that are known to be + equal or known to be non-equal. It will now also efficiently reject impossible + if-branches between known comparison expressions. (Incorrectly stated as a + 11.0.0 feature in the previous release notes) + +.. 820e8d8656ec [Analyzer][WebKit] UncountedLambdaCaptureChecker +- New checker: :ref:`webkit.UncountedLambdaCapturesChecker` + is a WebKit coding convention checker that flags raw pointers to + reference-counted objects captured by lambdas and suggests using intrusive + reference-counting smart pointers instead. + +.. 8a64689e264c [Analyzer][WebKit] UncountedLocalVarsChecker +- New checker: :ref:`alpha.webkit.UncountedLocalVarsChecker` + is a WebKit coding convention checker that intends to make sure that any + uncounted local variable is backed by a ref-counted object with lifetime that + is strictly larger than the scope of the uncounted local variable. + +.. i914f6c4ff8a4 [StaticAnalyzer] Support struct annotations in FuchsiaHandleChecker +- ``fuchia.HandleChecker`` now recognizes handles in structs; All the handles + referenced by the structure (direct value or ptr) would be treated as + containing the release/use/acquire annotations directly. + +.. 8deaec122ec6 [analyzer] Update Fuchsia checker to catch releasing unowned handles. +- Fuchsia checkers can detect the release of an unowned handle. + +- Numerous fixes and improvements to bug report generation. .. _release-notes-ubsan: diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index b47be97eef964ce0465c46e0dc00fdf907309f0d..d851845396ac4d28851d2551007a653b36bf5cd9 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -2538,6 +2538,8 @@ We also define a set of safe transformations which if passed a safe value as an - casts - unary operators like ``&`` or ``*`` +.. _alpha-webkit-UncountedLocalVarsChecker: + alpha.webkit.UncountedLocalVarsChecker """""""""""""""""""""""""""""""""""""" The goal of this rule is to make sure that any uncounted local variable is backed by a ref-counted object with lifetime that is strictly larger than the scope of the uncounted local variable. To be on the safe side we require the scope of an uncounted variable to be embedded in the scope of ref-counted object that backs it. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ce47d54e44b0b0733f82fd121f680fa500f340d1..ae69a68608b70804e99fa307f0759d54c4282fb3 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -538,6 +538,9 @@ private: /// need them (like static local vars). llvm::MapVector MangleNumbers; llvm::MapVector StaticLocalNumbers; + /// Mapping the associated device lambda mangling number if present. + mutable llvm::DenseMap + DeviceLambdaManglingNumbers; /// Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. diff --git a/clang/include/clang/AST/ASTDumper.h b/clang/include/clang/AST/ASTDumper.h index a154bc2db3a7e4ab6510e25bca61bf0320cf5b50..a75bcea190c2fb921d765eb2a70233e3179d83b5 100644 --- a/clang/include/clang/AST/ASTDumper.h +++ b/clang/include/clang/AST/ASTDumper.h @@ -43,6 +43,7 @@ public: void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); void VisitClassTemplateDecl(const ClassTemplateDecl *D); void VisitVarTemplateDecl(const VarTemplateDecl *D); + void VisitCompoundStmt(const CompoundStmt *Node); }; } // namespace clang diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 47c282f0a63dda8bdd160ca07e047769a3c7e4a3..d671f654aed873d53542e4a825335039cff40c18 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2047,6 +2047,14 @@ public: return hasBody(Definition); } + void setSafeSpecifier(SafeScopeSpecifier SafeSpec) { + FunctionDeclBits.SafeSpecifier = SafeSpec; + } + + SafeScopeSpecifier getSafeSpecifier() const { + return (SafeScopeSpecifier) FunctionDeclBits.SafeSpecifier; + } + /// Returns whether the function has a trivial body that does not require any /// specific codegen. bool hasTrivialBody() const; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 15eb29f725397fcaf879267cfe249acdc8a63188..e0a75d099fbe9e34387490b5662070b70cfd34e5 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1553,6 +1553,8 @@ class DeclContext { /// have a body, once we're done parsing it. uint64_t WillHaveBody : 1; + uint64_t SafeSpecifier : 2; + /// Indicates that this function is a multiversioned /// function using attribute 'target'. uint64_t IsMultiVersion : 1; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index e32101bb2276810c86baffc8a6cd46ffa1e20493..89006b1cfa7f4c867f11d31306e22ef2d2c7c35f 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1735,6 +1735,12 @@ public: getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage; } + /// Set the device side mangling number. + void setDeviceLambdaManglingNumber(unsigned Num) const; + + /// Retrieve the device side mangling number. + unsigned getDeviceLambdaManglingNumber() const; + /// Returns the inheritance model used for this record. MSInheritanceModel getMSInheritanceModel() const; diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index 0e8d6dd53d8a6014c245c8098fb2340b55d53a3c..7b6495d85eb6ed099ebd25ac2c90e6c48f7dd906 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -96,6 +96,9 @@ public: virtual bool shouldMangleCXXName(const NamedDecl *D) = 0; virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0; + virtual bool isDeviceMangleContext() const { return false; } + virtual void setDeviceMangleContext(bool) {} + // FIXME: consider replacing raw_ostream & with something like SmallString &. void mangleName(GlobalDecl GD, raw_ostream &); virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0; diff --git a/clang/include/clang/AST/MangleNumberingContext.h b/clang/include/clang/AST/MangleNumberingContext.h index f1ca6a05dbafe9172d995a6c586c4f882e85db76..eb33759682d6f3473a7489003bcb6a2c3ef4e756 100644 --- a/clang/include/clang/AST/MangleNumberingContext.h +++ b/clang/include/clang/AST/MangleNumberingContext.h @@ -52,6 +52,11 @@ public: /// this context. virtual unsigned getManglingNumber(const TagDecl *TD, unsigned MSLocalManglingNumber) = 0; + + /// Retrieve the mangling number of a new lambda expression with the + /// given call operator within the device context. No device number is + /// assigned if there's no device numbering context is associated. + virtual unsigned getDeviceManglingNumber(const CXXMethodDecl *) { return 0; } }; } // end namespace clang diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 505ea700fd0e0cfb5220dd7a17d30402fc3b7764..7870cea198a7f50e1ead30b5dac892c02cd92e84 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -186,6 +186,9 @@ public: /// code, e.g., implicit constructors and destructors. bool shouldVisitImplicitCode() const { return false; } + /// Return whether this visitor should recurse into lambda body + bool shouldVisitLambdaBody() const { return true; } + /// Return whether this visitor should traverse post-order. bool shouldTraversePostOrder() const { return false; } @@ -2057,6 +2060,15 @@ bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { // by clang. (!D->isDefaulted() || getDerived().shouldVisitImplicitCode()); + if (const auto *MD = dyn_cast(D)) { + if (const CXXRecordDecl *RD = MD->getParent()) { + if (RD->isLambda() && + declaresSameEntity(RD->getLambdaCallOperator(), MD)) { + VisitBody = VisitBody && getDerived().shouldVisitLambdaBody(); + } + } + } + if (VisitBody) { TRY_TO(TraverseStmt(D->getBody())); // Function body. } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index c2e69a91e55d0986852b9171c6cad38fcd1bc6bf..24867111e116b44f9c9c669bb805bad41a80f938 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -20,6 +20,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerIntPair.h" @@ -1403,18 +1404,25 @@ class CompoundStmt final : public Stmt, /// The location of the closing "}". LBraceLoc is stored in CompoundStmtBits. SourceLocation RBraceLoc; - CompoundStmt(ArrayRef Stmts, SourceLocation LB, SourceLocation RB); - explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) {} + SafeScopeSpecifier SafeSpec; + SourceLocation SafeLoc; + + CompoundStmt(ArrayRef Stmts, SourceLocation LB, SourceLocation RB, + SafeScopeSpecifier SafeSpec = SS_None, SourceLocation SafeLoc = SourceLocation()); + explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty), + SafeSpec(SS_None), SafeLoc() {} void setStmts(ArrayRef Stmts); public: static CompoundStmt *Create(const ASTContext &C, ArrayRef Stmts, - SourceLocation LB, SourceLocation RB); + SourceLocation LB, SourceLocation RB, + SafeScopeSpecifier SafeSpec = SS_None, + SourceLocation SafeLoc = SourceLocation()); // Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), RBraceLoc(Loc) { + : Stmt(CompoundStmtClass), RBraceLoc(Loc), SafeSpec(SS_None), SafeLoc() { CompoundStmtBits.NumStmts = 0; CompoundStmtBits.LBraceLoc = Loc; } @@ -1499,6 +1507,18 @@ public: return const_cast(this)->getStmtExprResult(); } + SafeScopeSpecifier getSafeSpecifier() const { + return SafeSpec; + } + + void setSafeSpecifier(SafeScopeSpecifier spec) { + SafeSpec = spec; + } + + SourceLocation getSafeSpecifierLoc() const { + return SafeLoc; + } + SourceLocation getBeginLoc() const { return CompoundStmtBits.LBraceLoc; } SourceLocation getEndLoc() const { return RBraceLoc; } diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 6f6dfab59a391b308ab2a51309d41d9f46d652d9..031fa4682c3abed38768e290669c0d532d3a7964 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -344,7 +344,7 @@ extern const internal::VariadicAllOfMatcher decl; /// int number = 42; /// auto [foo, bar] = std::make_pair{42, 42}; /// \endcode -extern const internal::VariadicAllOfMatcher +extern const internal::VariadicDynCastAllOfMatcher decompositionDecl; /// Matches a declaration of a linkage specification. diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index bfd50f6a6779bf0ef1bad040506a7869c0d8c668..1e41b7312314124992f05120a9fa5f655dfc383b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1790,8 +1790,8 @@ def NoSplitStack : InheritableAttr { def NonNull : InheritableParamAttr { let Spellings = [GCC<"nonnull">]; - let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag, - "functions, methods, and parameters">; + let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar, Var, Field], WarnDiag, + "functions, methods, and parameters (EnhanceC: additional applies to vars and fields)">; let Args = [VariadicParamIdxArgument<"Args">]; let AdditionalMembers = [{ bool isNonNull(unsigned IdxAST) const { @@ -1809,7 +1809,7 @@ def NonNull : InheritableParamAttr { def ReturnsNonNull : InheritableAttr { let Spellings = [GCC<"returns_nonnull">]; - let Subjects = SubjectList<[ObjCMethod, Function]>; + let Subjects = SubjectList<[ObjCMethod, Function, Var, Field]>; let Documentation = [ReturnsNonNullDocs]; } @@ -3684,3 +3684,81 @@ def EnforceTCBLeaf : InheritableAttr { let Documentation = [EnforceTCBLeafDocs]; bit InheritEvenIfAlreadyPresent = 1; } + +// EnhanceC attributes +def Count : InheritableParamAttr { + let Spellings = [GNU<"count">]; + let Subjects = SubjectList<[Function, ParmVar, Field, Var]>; + let Documentation = [Undocumented]; + let Args = [ExprArgument<"LenExpr">, VariadicParamIdxArgument<"Index">]; + let InheritEvenIfAlreadyPresent = 1; + let LateParsed = 1; + let TemplateDependent = 1; +} + +def ReturnsCount : InheritableAttr { + let Spellings = [GNU<"returns_count">]; + let Subjects = SubjectList<[Function, Var, Field]>; + let Documentation = [Undocumented]; + let Args = [ExprArgument<"LenExpr">]; + let InheritEvenIfAlreadyPresent = 1; + let LateParsed = 1; + let TemplateDependent = 1; +} + +def CountIndex : InheritableParamAttr { + let Spellings = [GNU<"count_index">]; + let Subjects = SubjectList<[Function, ParmVar, Field, Var]>; + let Documentation = [Undocumented]; + let Args = [ParamIdxArgument<"LenVarIndex">, VariadicParamIdxArgument<"Index">]; + let InheritEvenIfAlreadyPresent = 1; + let TemplateDependent = 1; +} + +def ReturnsCountIndex : InheritableAttr { + let Spellings = [GNU<"returns_count_index">]; + let Subjects = SubjectList<[Function, Field, Var]>; + let Documentation = [Undocumented]; + let Args = [ParamIdxArgument<"LenVarIndex">]; + let InheritEvenIfAlreadyPresent = 1; + let TemplateDependent = 1; +} + +// byte_count +def ByteCount : InheritableParamAttr { + let Spellings = [GNU<"byte_count">]; + let Subjects = SubjectList<[Function, ParmVar, Field, Var]>; + let Documentation = [Undocumented]; + let Args = [ExprArgument<"LenExpr">, VariadicParamIdxArgument<"Index">]; + let InheritEvenIfAlreadyPresent = 1; + let LateParsed = 1; + let TemplateDependent = 1; +} + +def ReturnsByteCount : InheritableAttr { + let Spellings = [GNU<"returns_byte_count">]; + let Subjects = SubjectList<[Function, Var, Field]>; + let Documentation = [Undocumented]; + let Args = [ExprArgument<"LenExpr">]; + let InheritEvenIfAlreadyPresent = 1; + let LateParsed = 1; + let TemplateDependent = 1; +} + +def ByteCountIndex : InheritableParamAttr { + let Spellings = [GNU<"byte_count_index">]; + let Subjects = SubjectList<[Function, ParmVar, Field, Var]>; + let Documentation = [Undocumented]; + let Args = [ParamIdxArgument<"LenVarIndex">, VariadicParamIdxArgument<"Index">]; + let InheritEvenIfAlreadyPresent = 1; + let TemplateDependent = 1; +} + +def ReturnsByteCountIndex : InheritableAttr { + let Spellings = [GNU<"returns_byte_count_index">]; + let Subjects = SubjectList<[Function, Var, Field]>; + let Documentation = [Undocumented]; + let Args = [ParamIdxArgument<"LenVarIndex">]; + let InheritEvenIfAlreadyPresent = 1; + let TemplateDependent = 1; +} diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 5c8af65326edb7996c314b04aabf5281f2f95c26..9d53b5b923bb2641c212acb688ab452b5de5a3f0 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -266,6 +266,9 @@ CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate. +/// Treat loops as finite: language, always, never. +ENUM_CODEGENOPT(FiniteLoops, FiniteLoopsKind, 2, FiniteLoopsKind::Language) + /// Attempt to use register sized accesses to bit-fields in structures, when /// possible. CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 73d41e3293c66102513d090c24df7dfea8b8b4e8..c550817f0f69f4ddb2a9199436c481cdf253d8b9 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -140,6 +140,12 @@ public: All, // Keep all frame pointers. }; + enum FiniteLoopsKind { + Language, // Not specified, use language standard. + Always, // All loops are assumed to be finite. + Never, // No loop is assumed to be finite. + }; + /// The code model to use (-mcmodel). std::string CodeModel; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 67c59f3ca09a71b843d17f941fef2ebae628b16f..b24dac80502f8090809f6597c84c4559d097d1c0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2892,9 +2892,22 @@ def err_attribute_only_once_per_parameter : Error< "%0 attribute can only be applied once per parameter">; def err_mismatched_uuid : Error<"uuid does not match previous declaration">; def note_previous_uuid : Note<"previous uuid specified here">; +// EnhanceC def warn_attribute_pointers_only : Warning< - "%0 attribute only applies to%select{| constant}1 pointer arguments">, + "(EnhanceC) %0 attribute only applies to%select{| constant}1 pointer arguments, vars or fields)">, InGroup; +def warn_attribute_no_pointers : Warning< + "(EnhanceC) %0 attribute applied to function with no pointer arguments">, + InGroup; +def err_attribute_redundant_pointers : Error< + "(EnhanceC) %0 attribute applied to function with more than one pointer arguments, " + "please specify the index argument in the %0 attribute">; +def warn_attribute_function_pointer : Warning< + "(EnhanceC) %0 attribute applied to function and function type pointer">, + InGroup; +def err_attribute_zero_pointer : Error< + "(EnhanceC) %0 attribute: The number of pointer arguments index cannot be zero">; + def err_attribute_pointers_only : Error; def err_attribute_integers_only : Error< "%0 attribute argument may only refer to a function parameter of integer " diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 07d8177b8ab2fb01969c494b1b238f607e306cff..c2736f90b1f5a95864bf382f28aa712286e22b83 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -371,6 +371,12 @@ namespace clang { } llvm_unreachable("Unknown AccessSpecifier"); } + + enum SafeScopeSpecifier { + SS_None = 0, + SS_Safe = 1, + SS_Unsafe = 2, + }; } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 572ebae6618db1added1115b9d0d8d15f647669f..b6e7b335bfb7934a480ff83215ab894666c60a99 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -690,6 +690,10 @@ ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) ALIAS("_inline" , inline , KEYMS) ALIAS("_declspec" , __declspec , KEYMS) +// safe region key word +KEYWORD(__Safe__ , KEYALL) +KEYWORD(__Unsafe__ , KEYALL) + // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) @@ -769,6 +773,11 @@ ANNOTATION(decltype) // annotation for a decltype expression, // one 'pragma_unused' annotation token followed by the argument token. PRAGMA_ANNOTATION(pragma_unused) +// Annotations for SAFE pragma +// The lexer produces these so that they only take effect when the parser +// handles #pragma SAFE ... directives. +PRAGMA_ANNOTATION(pragma_safe) + // Annotation for #pragma GCC visibility... // The lexer produces these so that they only take effect when the parser // handles them. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 42c5319041d09e2965d84c86345b95c0500bf0ad..817798926650f0b368b14725011bc904f02df77b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1147,7 +1147,7 @@ def fprofile_update_EQ : Joined<["-"], "fprofile-update=">, defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling", CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse, PosFlag, NegFlag, - BothFlags<[NoXarchOption, CC1Option], " pseudo probes for sample profiler">>; + BothFlags<[NoXarchOption, CC1Option], " pseudo probes for sample profiling">>; def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; @@ -2410,6 +2410,11 @@ def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group, defm reroll_loops : BoolFOption<"reroll-loops", CodeGenOpts<"RerollLoops">, DefaultFalse, PosFlag, NegFlag>; +def ffinite_loops: Flag<["-"], "ffinite-loops">, Group, + HelpText<"Assume all loops are finite.">, Flags<[CC1Option]>; +def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group, + HelpText<"Do not assume that any loop is finite.">, Flags<[CC1Option]>; + def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/include/clang/Lex/VariadicMacroSupport.h b/clang/include/clang/Lex/VariadicMacroSupport.h index 989e0ac703c9b7cb674ff3939d4b4dbad0e70989..119f02201fc614404e9acd2da1545252a4a1d675 100644 --- a/clang/include/clang/Lex/VariadicMacroSupport.h +++ b/clang/include/clang/Lex/VariadicMacroSupport.h @@ -39,17 +39,14 @@ namespace clang { 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!")); + assert(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); + Ident__VA_OPT__->setIsPoisoned(false); } /// Client code should call this function as soon as the Preprocessor has @@ -58,8 +55,7 @@ namespace clang { /// (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); + Ident__VA_OPT__->setIsPoisoned(true); } ~VariadicMacroScopeGuard() { exitScope(); } diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 02aab3b43be0b3a70cc9a52f2fceebf6323d966a..11bd1704c4cede815006691d7509e1e828ee950f 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -208,6 +208,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr AttributePragmaHandler; std::unique_ptr MaxTokensHerePragmaHandler; std::unique_ptr MaxTokensTotalPragmaHandler; + std::unique_ptr SafeHandler; std::unique_ptr CommentSemaHandler; @@ -771,6 +772,8 @@ private: void HandlePragmaAttribute(); + void HandlePragmaSafe(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. @@ -2084,7 +2087,9 @@ private: unsigned ScopeFlags); void ParseCompoundStatementLeadingPragmas(); bool ConsumeNullStmt(StmtVector &Stmts); - StmtResult ParseCompoundStatementBody(bool isStmtExpr = false); + StmtResult ParseCompoundStatementBody(bool isStmtExpr = false, + SafeScopeSpecifier SafeSpec = SS_None, + SourceLocation SafeLoc = SourceLocation()); bool ParseParenExprOrCondition(StmtResult *InitStmt, Sema::ConditionResult &CondResult, SourceLocation Loc, Sema::ConditionKind CK, diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 3b16295941e48ba9501d838327cbfb6e73fabd47..82c892c71bd715dc79f700d1288ac9e1e06db065 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -366,6 +366,10 @@ private: /// ExplicitSpecifier - Store information about explicit spicifer. ExplicitSpecifier FS_explicit_specifier; + SafeScopeSpecifier FS_safe_specified; + + SourceLocation FS_safe_loc; + // attributes. ParsedAttributes Attrs; @@ -433,7 +437,9 @@ public: FS_noreturn_specified(false), Friend_specified(false), ConstexprSpecifier( static_cast(ConstexprSpecKind::Unspecified)), - FS_explicit_specifier(), Attrs(attrFactory), writtenBS(), + FS_explicit_specifier(), + FS_safe_specified(SS_None), FS_safe_loc(), + Attrs(attrFactory), writtenBS(), ObjCQualifiers(nullptr) {} // storage-class-specifier @@ -588,6 +594,14 @@ public: : SourceRange(FS_explicitLoc); } + SafeScopeSpecifier getSafeSpecifier() const { + return FS_safe_specified; + } + + SourceLocation getSafeSpecifierLoc() const { + return FS_safe_loc; + } + bool isNoreturnSpecified() const { return FS_noreturn_specified; } SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; } @@ -601,6 +615,8 @@ public: FS_explicit_specifier = ExplicitSpecifier(); FS_explicitLoc = SourceLocation(); FS_explicitCloseParenLoc = SourceLocation(); + FS_safe_specified = SS_None; + FS_safe_loc = SourceLocation(); FS_noreturn_specified = false; FS_noreturnLoc = SourceLocation(); } @@ -737,6 +753,8 @@ public: SourceLocation CloseParenLoc); bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); + bool setFunctionSafeSpecifier(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, SafeScopeSpecifier SafeSpec); bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7f7c84eb1b1d8ed9f9c5c19421eca90cae4f609e..cc9f94d908be1d08dc391fb7b221b444e820bb51 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4579,7 +4579,28 @@ public: void ActOnAfterCompoundStatementLeadingPragmas(); void ActOnFinishOfCompoundStmt(); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, - ArrayRef Elts, bool isStmtExpr); + ArrayRef Elts, bool isStmtExpr, + SafeScopeSpecifier SafeSpec = SS_None, + SourceLocation SafeLoc = SourceLocation()); + +private: + SafeScopeSpecifier PragmaSafeInfo = SS_None; + +public: + enum PragmaSafeStatus { + PSS_On, + PSS_Off, + }; + + void ActOnPragmaSafe(PragmaSafeStatus St); + + SafeScopeSpecifier GetPragmaSafeInfo() { + return PragmaSafeInfo; + } + + void SetPragmaSafeInfo(SafeScopeSpecifier SafeSpec) { + PragmaSafeInfo = SafeSpec; + } /// A RAII object to enter scope of a compound statement. class CompoundScopeRAII { @@ -6558,7 +6579,7 @@ public: /// Number lambda for linkage purposes if necessary. void handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, - Optional> Mangling = None); + Optional> Mangling = None); /// Endow the lambda scope info with the relevant properties. void buildLambdaScope(sema::LambdaScopeInfo *LSI, @@ -11948,8 +11969,8 @@ public: /// if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported)) /// return ExprError(); /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID); + SemaDiagnosticBuilder + diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD); /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current /// context is "used as host code". @@ -11965,17 +11986,19 @@ public: /// return ExprError(); /// // Otherwise, continue parsing as normal. SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID); + unsigned DiagID, FunctionDecl *FD); - SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID); + SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, + FunctionDecl *FD = nullptr); SemaDiagnosticBuilder targetDiag(SourceLocation Loc, - const PartialDiagnostic &PD) { - return targetDiag(Loc, PD.getDiagID()) << PD; + const PartialDiagnostic &PD, + FunctionDecl *FD = nullptr) { + return targetDiag(Loc, PD.getDiagID(), FD) << PD; } /// Check if the expression is allowed to be used in expressions for the /// offloading devices. - void checkDeviceDecl(const ValueDecl *D, SourceLocation Loc); + void checkDeviceDecl(ValueDecl *D, SourceLocation Loc); enum CUDAFunctionTarget { CFT_Device, diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 3d368a0a7b63e72b903f2087a172da7c02c26917..269b2a7de6b39b048027d4523808ed1728b2b125 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -151,6 +151,17 @@ void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D, false); } +void ASTDumper::VisitCompoundStmt(const CompoundStmt *Node) { + VisitStmt(Node); + SafeScopeSpecifier SafeSpec = Node->getSafeSpecifier(); + + if (SafeSpec == SS_Safe) { + OS << " safe"; + } else if (SafeSpec == SS_Unsafe) { + OS << " unsafe"; + } +} + //===----------------------------------------------------------------------===// // Type method implementations //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 085c50c0667be3874123c738a17e88161405c0e7..dce23410294ee796578cc155ab13b70d4d5140bb 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2848,6 +2848,8 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { return CDeclOrErr.takeError(); D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr, DCXX->hasKnownLambdaInternalLinkage()); + D2CXX->setDeviceLambdaManglingNumber( + DCXX->getDeviceLambdaManglingNumber()); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in // Sema::ActOnStartCXXMemberDeclarations @@ -6079,9 +6081,14 @@ ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { if (!ToRBracLocOrErr) return ToRBracLocOrErr.takeError(); + ExpectedSLoc ToSafeSpecifierLocOrErr = import(S->getSafeSpecifierLoc()); + if (!ToSafeSpecifierLocOrErr) + return ToSafeSpecifierLocOrErr.takeError(); + return CompoundStmt::Create( Importer.getToContext(), ToStmts, - *ToLBracLocOrErr, *ToRBracLocOrErr); + *ToLBracLocOrErr, *ToRBracLocOrErr, + S->getSafeSpecifier(), *ToSafeSpecifierLocOrErr); } ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index 31cb369187266cd41ed0d722515e7d04814d9a00..ca9424bcb7a49878248dc33a4203a7ddf3893f13 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -22,8 +22,9 @@ class ASTContext; class CXXConstructorDecl; class DeclaratorDecl; class Expr; -class MemberPointerType; +class MangleContext; class MangleNumberingContext; +class MemberPointerType; /// Implements C++ ABI-specific semantic analysis functions. class CXXABI { @@ -75,6 +76,8 @@ public: /// Creates an instance of a C++ ABI class. CXXABI *CreateItaniumCXXABI(ASTContext &Ctx); CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx); +std::unique_ptr +createItaniumNumberingContext(MangleContext *); } #endif diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index feb9b0645ebcb8ba0848496b381e39296ae89da2..3ebcdcd3ccc2e5f96cb3625be97e2335c2943aa7 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2848,6 +2848,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.UsesFPIntrin = false; FunctionDeclBits.HasSkippedBody = false; FunctionDeclBits.WillHaveBody = false; + FunctionDeclBits.SafeSpecifier = SS_None; FunctionDeclBits.IsMultiVersion = false; FunctionDeclBits.IsCopyDeductionCandidate = false; FunctionDeclBits.HasODRHash = false; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 0368ada0b81c4bcd2db23fbbff105db71950488b..0375f9b4432eee9fb0f6c2743744852b79f1a63a 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1593,6 +1593,20 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const { return getLambdaData().ContextDecl.get(Source); } +void CXXRecordDecl::setDeviceLambdaManglingNumber(unsigned Num) const { + assert(isLambda() && "Not a lambda closure type!"); + if (Num) + getASTContext().DeviceLambdaManglingNumbers[this] = Num; +} + +unsigned CXXRecordDecl::getDeviceLambdaManglingNumber() const { + assert(isLambda() && "Not a lambda closure type!"); + auto I = getASTContext().DeviceLambdaManglingNumbers.find(this); + if (I != getASTContext().DeviceLambdaManglingNumbers.end()) + return I->second; + return 0; +} + static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T = cast(Conv->getUnderlyingDecl()->getAsFunction()) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 56181bbe116684941fcc51d24c6e57ecd95f44fe..4b3258be0989450f67727c500378b1c42d9ed6ba 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3497,8 +3497,8 @@ static bool diagnoseMutableFields(EvalInfo &Info, const Expr *E, AccessKinds AK, static bool lifetimeStartedInEvaluation(EvalInfo &Info, APValue::LValueBase Base, bool MutableSubobject = false) { - // A temporary we created. - if (Base.getCallIndex()) + // A temporary or transient heap allocation we created. + if (Base.getCallIndex() || Base.is()) return true; switch (Info.IsEvaluatingDecl) { @@ -10009,6 +10009,7 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { auto *CaptureInitIt = E->capture_init_begin(); const LambdaCapture *CaptureIt = ClosureClass->captures_begin(); bool Success = true; + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(ClosureClass); for (const auto *Field : ClosureClass->fields()) { assert(CaptureInitIt != E->capture_init_end()); // Get the initializer for this field @@ -10019,8 +10020,13 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { if (!CurFieldInit) return Error(E); + LValue Subobject = This; + + if (!HandleLValueMember(Info, E, Subobject, Field, &Layout)) + return false; + APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); - if (!EvaluateInPlace(FieldVal, Info, This, CurFieldInit)) { + if (!EvaluateInPlace(FieldVal, Info, Subobject, CurFieldInit)) { if (!Info.keepEvaluatingAfterFailure()) return false; Success = false; @@ -10403,6 +10409,8 @@ static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This, // Return true iff the given array filler may depend on the element index. static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) { + if (!FillerExpr) + return false; // For now, just allow non-class value-initialization and initialization // lists comprised of them. if (isa(FillerExpr)) @@ -14568,6 +14576,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { /// an object can indirectly refer to subobjects which were initialized earlier. static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes) { + if (!E) + return false; assert(!E->isValueDependent()); if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) @@ -14786,11 +14796,14 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, static bool EvaluateDestruction(const ASTContext &Ctx, APValue::LValueBase Base, APValue DestroyedValue, QualType Type, - SourceLocation Loc, Expr::EvalStatus &EStatus) { - EvalInfo Info(Ctx, EStatus, EvalInfo::EM_ConstantExpression); + SourceLocation Loc, Expr::EvalStatus &EStatus, + bool IsConstantDestruction) { + EvalInfo Info(Ctx, EStatus, + IsConstantDestruction ? EvalInfo::EM_ConstantExpression + : EvalInfo::EM_ConstantFold); Info.setEvaluatingDecl(Base, DestroyedValue, EvalInfo::EvaluatingDeclKind::Dtor); - Info.InConstantContext = true; + Info.InConstantContext = IsConstantDestruction; LValue LVal; LVal.set(Base); @@ -14844,7 +14857,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, // If this is a class template argument, it's required to have constant // destruction too. if (Kind == ConstantExprKind::ClassTemplateArgument && - (!EvaluateDestruction(Ctx, Base, Result.Val, T, getBeginLoc(), Result) || + (!EvaluateDestruction(Ctx, Base, Result.Val, T, getBeginLoc(), Result, + true) || Result.HasSideEffects)) { // FIXME: Prefix a note to indicate that the problem is lack of constant // destruction. @@ -14910,6 +14924,10 @@ bool VarDecl::evaluateDestruction( Expr::EvalStatus EStatus; EStatus.Diag = &Notes; + // Only treat the destruction as constant destruction if we formally have + // constant initialization (or are usable in a constant expression). + bool IsConstantDestruction = hasConstantInitialization(); + // Make a copy of the value for the destructor to mutate, if we know it. // Otherwise, treat the value as default-initialized; if the destructor works // anyway, then the destruction is constant (and must be essentially empty). @@ -14920,7 +14938,8 @@ bool VarDecl::evaluateDestruction( return false; if (!EvaluateDestruction(getASTContext(), this, std::move(DestroyedValue), - getType(), getLocation(), EStatus) || + getType(), getLocation(), EStatus, + IsConstantDestruction) || EStatus.HasSideEffects) return false; diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 069add8464ae8ae00350151286a0eca207471f9d..be10258a2d774e8fbd4d7cb02e209543cf7d2568 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -258,3 +258,9 @@ public: CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) { return new ItaniumCXXABI(Ctx); } + +std::unique_ptr +clang::createItaniumNumberingContext(MangleContext *Mangler) { + return std::make_unique( + cast(Mangler)); +} diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 6c8d5687c64a8aedab01bb2169e8f79618a8ad89..5cad84a96845b10a019973e6d161fa065ecc9d2d 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -125,6 +125,8 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; + bool IsDevCtx = false; + public: explicit ItaniumMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) @@ -137,6 +139,10 @@ public: bool shouldMangleStringLiteral(const StringLiteral *) override { return false; } + + bool isDeviceMangleContext() const override { return IsDevCtx; } + void setDeviceMangleContext(bool IsDev) override { IsDevCtx = IsDev; } + void mangleCXXName(GlobalDecl GD, raw_ostream &) override; void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &) override; @@ -546,8 +552,8 @@ private: unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); - void mangleDeclRefExpr(const NamedDecl *D); - void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); + void mangleExpression(const Expr *E, unsigned Arity = UnknownArity, + bool AsTemplateArg = false); void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); void mangleCXXDtorType(CXXDtorType T); @@ -558,6 +564,7 @@ private: unsigned NumTemplateArgs); void mangleTemplateArgs(TemplateName TN, const TemplateArgumentList &AL); void mangleTemplateArg(TemplateArgument A, bool NeedExactType); + void mangleTemplateArgExpr(const Expr *E); void mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel, bool NeedExactType = false); @@ -726,9 +733,17 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { EnableIfAttr *EIA = dyn_cast(*I); if (!EIA) continue; - Out << 'X'; - mangleExpression(EIA->getCond()); - Out << 'E'; + if (Context.getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver11) { + mangleTemplateArgExpr(EIA->getCond()); + } else { + // Prior to Clang 12, we hardcoded the X/E around enable-if's argument, + // even though should not include an X/E around + // . + Out << 'X'; + mangleExpression(EIA->getCond()); + Out << 'E'; + } } Out << 'E'; FunctionTypeDepth.pop(Saved); @@ -1837,7 +1852,15 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // (in lexical order) with that same and context. // // The AST keeps track of the number for us. - unsigned Number = Lambda->getLambdaManglingNumber(); + // + // In CUDA/HIP, to ensure the consistent lamba numbering between the device- + // and host-side compilations, an extra device mangle context may be created + // if the host-side CXX ABI has different numbering for lambda. In such case, + // if the mangle context is that device-side one, use the device-side lambda + // mangling number for this lambda. + unsigned Number = Context.isDeviceMangleContext() + ? Lambda->getDeviceLambdaManglingNumber() + : Lambda->getLambdaManglingNumber(); assert(Number > 0 && "Lambda should be mangled as an unnamed class"); if (Number > 1) mangleNumber(Number - 2); @@ -3528,8 +3551,8 @@ void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) { Out << "u" << VendorQualifier.size() << VendorQualifier; Out << "I"; - mangleTemplateArg(T->getRowExpr(), false); - mangleTemplateArg(T->getColumnExpr(), false); + mangleTemplateArgExpr(T->getRowExpr()); + mangleTemplateArgExpr(T->getColumnExpr()); mangleType(T->getElementType()); Out << "E"; } @@ -3871,33 +3894,8 @@ void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) { mangleExpression(InitList->getInit(i)); } -void CXXNameMangler::mangleDeclRefExpr(const NamedDecl *D) { - switch (D->getKind()) { - default: - // ::= L E # external name - Out << 'L'; - mangle(D); - Out << 'E'; - break; - - case Decl::ParmVar: - mangleFunctionParam(cast(D)); - break; - - case Decl::EnumConstant: { - const EnumConstantDecl *ED = cast(D); - mangleIntegerLiteral(ED->getType(), ED->getInitVal()); - break; - } - - case Decl::NonTypeTemplateParm: - const NonTypeTemplateParmDecl *PD = cast(D); - mangleTemplateParameter(PD->getDepth(), PD->getIndex()); - break; - } -} - -void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { +void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, + bool AsTemplateArg) { // ::= // ::= // ::= @@ -3911,18 +3909,64 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // ::= at # alignof (a type) // ::= // ::= + // ::= fpT # 'this' expression (part of ) // ::= sr # dependent name // ::= sr # dependent template-id // ::= ds # expr.*expr // ::= sZ # size of a parameter pack // ::= sZ # size of a function parameter pack + // ::= u * E # vendor extended expression // ::= // ::= L E # integer literal - // ::= L E # floating literal + // ::= L E # floating literal + // ::= L E # string literal + // ::= L E # nullptr literal "LDnE" + // ::= L 0 E # null pointer template argument + // ::= L _ E # complex floating point literal (C99); not used by clang // ::= L E # external name - // ::= fpT # 'this' expression QualType ImplicitlyConvertedToType; + // A top-level expression that's not needs to be wrapped in + // X...E in a template arg. + bool IsPrimaryExpr = true; + auto NotPrimaryExpr = [&] { + if (AsTemplateArg && IsPrimaryExpr) + Out << 'X'; + IsPrimaryExpr = false; + }; + + auto MangleDeclRefExpr = [&](const NamedDecl *D) { + switch (D->getKind()) { + default: + // ::= L E # external name + Out << 'L'; + mangle(D); + Out << 'E'; + break; + + case Decl::ParmVar: + NotPrimaryExpr(); + mangleFunctionParam(cast(D)); + break; + + case Decl::EnumConstant: { + // + const EnumConstantDecl *ED = cast(D); + mangleIntegerLiteral(ED->getType(), ED->getInitVal()); + break; + } + + case Decl::NonTypeTemplateParm: + NotPrimaryExpr(); + const NonTypeTemplateParmDecl *PD = cast(D); + mangleTemplateParameter(PD->getDepth(), PD->getIndex()); + break; + } + }; + + // 'goto recurse' is used when handling a simple "unwrapping" node which + // produces no output, where ImplicitlyConvertedToType and AsTemplateArg need + // to be preserved. recurse: switch (E->getStmtClass()) { case Expr::NoStmtClass: @@ -3994,6 +4038,7 @@ recurse: case Expr::SourceLocExprClass: case Expr::BuiltinBitCastExprClass: { + NotPrimaryExpr(); if (!NullOut) { // As bad as this diagnostic is, it's better than crashing. DiagnosticsEngine &Diags = Context.getDiags(); @@ -4001,33 +4046,48 @@ recurse: "cannot yet mangle expression type %0"); Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() << E->getSourceRange(); + return; } break; } case Expr::CXXUuidofExprClass: { + NotPrimaryExpr(); const CXXUuidofExpr *UE = cast(E); - if (UE->isTypeOperand()) { - QualType UuidT = UE->getTypeOperand(Context.getASTContext()); - Out << "u8__uuidoft"; - mangleType(UuidT); + // As of clang 12, uuidof uses the vendor extended expression + // mangling. Previously, it used a special-cased nonstandard extension. + if (Context.getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver11) { + Out << "u8__uuidof"; + if (UE->isTypeOperand()) + mangleType(UE->getTypeOperand(Context.getASTContext())); + else + mangleTemplateArgExpr(UE->getExprOperand()); + Out << 'E'; } else { - Expr *UuidExp = UE->getExprOperand(); - Out << "u8__uuidofz"; - mangleExpression(UuidExp, Arity); + if (UE->isTypeOperand()) { + QualType UuidT = UE->getTypeOperand(Context.getASTContext()); + Out << "u8__uuidoft"; + mangleType(UuidT); + } else { + Expr *UuidExp = UE->getExprOperand(); + Out << "u8__uuidofz"; + mangleExpression(UuidExp); + } } break; } // Even gcc-4.5 doesn't mangle this. case Expr::BinaryConditionalOperatorClass: { + NotPrimaryExpr(); DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "?: operator with omitted middle operand cannot be mangled"); Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() << E->getSourceRange(); - break; + return; } // These are used for internal purposes and cannot be meaningfully mangled. @@ -4035,6 +4095,7 @@ recurse: llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); case Expr::InitListExprClass: { + NotPrimaryExpr(); Out << "il"; mangleInitListElements(cast(E)); Out << "E"; @@ -4042,6 +4103,7 @@ recurse: } case Expr::DesignatedInitExprClass: { + NotPrimaryExpr(); auto *DIE = cast(E); for (const auto &Designator : DIE->designators()) { if (Designator.isFieldDesignator()) { @@ -4063,27 +4125,27 @@ recurse: } case Expr::CXXDefaultArgExprClass: - mangleExpression(cast(E)->getExpr(), Arity); - break; + E = cast(E)->getExpr(); + goto recurse; case Expr::CXXDefaultInitExprClass: - mangleExpression(cast(E)->getExpr(), Arity); - break; + E = cast(E)->getExpr(); + goto recurse; case Expr::CXXStdInitializerListExprClass: - mangleExpression(cast(E)->getSubExpr(), Arity); - break; + E = cast(E)->getSubExpr(); + goto recurse; case Expr::SubstNonTypeTemplateParmExprClass: - mangleExpression(cast(E)->getReplacement(), - Arity); - break; + E = cast(E)->getReplacement(); + goto recurse; case Expr::UserDefinedLiteralClass: // We follow g++'s approach of mangling a UDL as a call to the literal // operator. case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { + NotPrimaryExpr(); const CallExpr *CE = cast(E); // ::= cp * E @@ -4114,6 +4176,7 @@ recurse: } case Expr::CXXNewExprClass: { + NotPrimaryExpr(); const CXXNewExpr *New = cast(E); if (New->isGlobalNew()) Out << "gs"; Out << (New->isArray() ? "na" : "nw"); @@ -4149,6 +4212,7 @@ recurse: } case Expr::CXXPseudoDestructorExprClass: { + NotPrimaryExpr(); const auto *PDE = cast(E); if (const Expr *Base = PDE->getBase()) mangleMemberExprBase(Base, PDE->isArrow()); @@ -4175,6 +4239,7 @@ recurse: } case Expr::MemberExprClass: { + NotPrimaryExpr(); const MemberExpr *ME = cast(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, @@ -4185,6 +4250,7 @@ recurse: } case Expr::UnresolvedMemberExprClass: { + NotPrimaryExpr(); const UnresolvedMemberExpr *ME = cast(E); mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, @@ -4195,6 +4261,7 @@ recurse: } case Expr::CXXDependentScopeMemberExprClass: { + NotPrimaryExpr(); const CXXDependentScopeMemberExpr *ME = cast(E); mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), @@ -4207,6 +4274,7 @@ recurse: } case Expr::UnresolvedLookupExprClass: { + NotPrimaryExpr(); const UnresolvedLookupExpr *ULE = cast(E); mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), ULE->getTemplateArgs(), ULE->getNumTemplateArgs(), @@ -4215,6 +4283,7 @@ recurse: } case Expr::CXXUnresolvedConstructExprClass: { + NotPrimaryExpr(); const CXXUnresolvedConstructExpr *CE = cast(E); unsigned N = CE->getNumArgs(); @@ -4225,7 +4294,7 @@ recurse: mangleType(CE->getType()); mangleInitListElements(IL); Out << "E"; - return; + break; } Out << "cv"; @@ -4237,14 +4306,17 @@ recurse: } case Expr::CXXConstructExprClass: { + // An implicit cast is silent, thus may contain . const auto *CE = cast(E); if (!CE->isListInitialization() || CE->isStdInitListInitialization()) { assert( CE->getNumArgs() >= 1 && (CE->getNumArgs() == 1 || isa(CE->getArg(1))) && "implicit CXXConstructExpr must have one argument"); - return mangleExpression(cast(E)->getArg(0)); + E = cast(E)->getArg(0); + goto recurse; } + NotPrimaryExpr(); Out << "il"; for (auto *E : CE->arguments()) mangleExpression(E); @@ -4253,6 +4325,7 @@ recurse: } case Expr::CXXTemporaryObjectExprClass: { + NotPrimaryExpr(); const auto *CE = cast(E); unsigned N = CE->getNumArgs(); bool List = CE->isListInitialization(); @@ -4282,17 +4355,20 @@ recurse: } case Expr::CXXScalarValueInitExprClass: + NotPrimaryExpr(); Out << "cv"; mangleType(E->getType()); Out << "_E"; break; case Expr::CXXNoexceptExprClass: + NotPrimaryExpr(); Out << "nx"; mangleExpression(cast(E)->getOperand()); break; case Expr::UnaryExprOrTypeTraitExprClass: { + // Non-instantiation-dependent traits are an integer literal. const UnaryExprOrTypeTraitExpr *SAE = cast(E); if (!SAE->isInstantiationDependent()) { @@ -4312,13 +4388,41 @@ recurse: break; } + NotPrimaryExpr(); // But otherwise, they are not. + + auto MangleAlignofSizeofArg = [&] { + if (SAE->isArgumentType()) { + Out << 't'; + mangleType(SAE->getArgumentType()); + } else { + Out << 'z'; + mangleExpression(SAE->getArgumentExpr()); + } + }; + switch(SAE->getKind()) { case UETT_SizeOf: Out << 's'; + MangleAlignofSizeofArg(); break; case UETT_PreferredAlignOf: + // As of clang 12, we mangle __alignof__ differently than alignof. (They + // have acted differently since Clang 8, but were previously mangled the + // same.) + if (Context.getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver11) { + Out << "u11__alignof__"; + if (SAE->isArgumentType()) + mangleType(SAE->getArgumentType()); + else + mangleTemplateArgExpr(SAE->getArgumentExpr()); + Out << 'E'; + break; + } + LLVM_FALLTHROUGH; case UETT_AlignOf: Out << 'a'; + MangleAlignofSizeofArg(); break; case UETT_VecStep: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -4336,17 +4440,11 @@ recurse: return; } } - if (SAE->isArgumentType()) { - Out << 't'; - mangleType(SAE->getArgumentType()); - } else { - Out << 'z'; - mangleExpression(SAE->getArgumentExpr()); - } break; } case Expr::CXXThrowExprClass: { + NotPrimaryExpr(); const CXXThrowExpr *TE = cast(E); // ::= tw # throw expression // ::= tr # rethrow @@ -4360,6 +4458,7 @@ recurse: } case Expr::CXXTypeidExprClass: { + NotPrimaryExpr(); const CXXTypeidExpr *TIE = cast(E); // ::= ti # typeid (type) // ::= te # typeid (expression) @@ -4374,6 +4473,7 @@ recurse: } case Expr::CXXDeleteExprClass: { + NotPrimaryExpr(); const CXXDeleteExpr *DE = cast(E); // ::= [gs] dl # [::] delete expr // ::= [gs] da # [::] delete [] expr @@ -4384,6 +4484,7 @@ recurse: } case Expr::UnaryOperatorClass: { + NotPrimaryExpr(); const UnaryOperator *UO = cast(E); mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()), /*Arity=*/1); @@ -4392,6 +4493,7 @@ recurse: } case Expr::ArraySubscriptExprClass: { + NotPrimaryExpr(); const ArraySubscriptExpr *AE = cast(E); // Array subscript is treated as a syntactically weird form of @@ -4403,6 +4505,7 @@ recurse: } case Expr::MatrixSubscriptExprClass: { + NotPrimaryExpr(); const MatrixSubscriptExpr *ME = cast(E); Out << "ixix"; mangleExpression(ME->getBase()); @@ -4413,6 +4516,7 @@ recurse: case Expr::CompoundAssignOperatorClass: // fallthrough case Expr::BinaryOperatorClass: { + NotPrimaryExpr(); const BinaryOperator *BO = cast(E); if (BO->getOpcode() == BO_PtrMemD) Out << "ds"; @@ -4425,6 +4529,7 @@ recurse: } case Expr::CXXRewrittenBinaryOperatorClass: { + NotPrimaryExpr(); // The mangled form represents the original syntax. CXXRewrittenBinaryOperator::DecomposedForm Decomposed = cast(E)->getDecomposedForm(); @@ -4436,6 +4541,7 @@ recurse: } case Expr::ConditionalOperatorClass: { + NotPrimaryExpr(); const ConditionalOperator *CO = cast(E); mangleOperatorName(OO_Conditional, /*Arity=*/3); mangleExpression(CO->getCond()); @@ -4451,19 +4557,22 @@ recurse: } case Expr::ObjCBridgedCastExprClass: { + NotPrimaryExpr(); // Mangle ownership casts as a vendor extended operator __bridge, // __bridge_transfer, or __bridge_retain. StringRef Kind = cast(E)->getBridgeKindName(); Out << "v1U" << Kind.size() << Kind; + mangleCastExpression(E, "cv"); + break; } - // Fall through to mangle the cast itself. - LLVM_FALLTHROUGH; case Expr::CStyleCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "cv"); break; case Expr::CXXFunctionalCastExprClass: { + NotPrimaryExpr(); auto *Sub = cast(E)->getSubExpr()->IgnoreImplicit(); // FIXME: Add isImplicit to CXXConstructExpr. if (auto *CCE = dyn_cast(Sub)) @@ -4483,22 +4592,28 @@ recurse: } case Expr::CXXStaticCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "sc"); break; case Expr::CXXDynamicCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "dc"); break; case Expr::CXXReinterpretCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "rc"); break; case Expr::CXXConstCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "cc"); break; case Expr::CXXAddrspaceCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "ac"); break; case Expr::CXXOperatorCallExprClass: { + NotPrimaryExpr(); const CXXOperatorCallExpr *CE = cast(E); unsigned NumArgs = CE->getNumArgs(); // A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax @@ -4512,9 +4627,8 @@ recurse: } case Expr::ParenExprClass: - mangleExpression(cast(E)->getSubExpr(), Arity); - break; - + E = cast(E)->getSubExpr(); + goto recurse; case Expr::ConceptSpecializationExprClass: { // ::= L E # external name @@ -4528,10 +4642,12 @@ recurse: } case Expr::DeclRefExprClass: - mangleDeclRefExpr(cast(E)->getDecl()); + // MangleDeclRefExpr helper handles primary-vs-nonprimary + MangleDeclRefExpr(cast(E)->getDecl()); break; case Expr::SubstNonTypeTemplateParmPackExprClass: + NotPrimaryExpr(); // FIXME: not clear how to mangle this! // template class A { // template void foo(U (&x)[N]...); @@ -4540,14 +4656,16 @@ recurse: break; case Expr::FunctionParmPackExprClass: { + NotPrimaryExpr(); // FIXME: not clear how to mangle this! const FunctionParmPackExpr *FPPE = cast(E); Out << "v110_SUBSTPACK"; - mangleDeclRefExpr(FPPE->getParameterPack()); + MangleDeclRefExpr(FPPE->getParameterPack()); break; } case Expr::DependentScopeDeclRefExprClass: { + NotPrimaryExpr(); const DependentScopeDeclRefExpr *DRE = cast(E); mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), DRE->getTemplateArgs(), DRE->getNumTemplateArgs(), @@ -4556,24 +4674,27 @@ recurse: } case Expr::CXXBindTemporaryExprClass: - mangleExpression(cast(E)->getSubExpr()); - break; + E = cast(E)->getSubExpr(); + goto recurse; case Expr::ExprWithCleanupsClass: - mangleExpression(cast(E)->getSubExpr(), Arity); - break; + E = cast(E)->getSubExpr(); + goto recurse; case Expr::FloatingLiteralClass: { + // const FloatingLiteral *FL = cast(E); mangleFloatLiteral(FL->getType(), FL->getValue()); break; } case Expr::FixedPointLiteralClass: + // Currently unimplemented -- might be in future? mangleFixedPointLiteral(); break; case Expr::CharacterLiteralClass: + // Out << 'L'; mangleType(E->getType()); Out << cast(E)->getValue(); @@ -4582,18 +4703,21 @@ recurse: // FIXME. __objc_yes/__objc_no are mangled same as true/false case Expr::ObjCBoolLiteralExprClass: + // Out << "Lb"; Out << (cast(E)->getValue() ? '1' : '0'); Out << 'E'; break; case Expr::CXXBoolLiteralExprClass: + // Out << "Lb"; Out << (cast(E)->getValue() ? '1' : '0'); Out << 'E'; break; case Expr::IntegerLiteralClass: { + // llvm::APSInt Value(cast(E)->getValue()); if (E->getType()->isSignedIntegerType()) Value.setIsSigned(true); @@ -4602,6 +4726,7 @@ recurse: } case Expr::ImaginaryLiteralClass: { + // const ImaginaryLiteral *IE = cast(E); // Mangle as if a complex literal. // Proposal from David Vandevoorde, 2010.06.30. @@ -4625,6 +4750,7 @@ recurse: } case Expr::StringLiteralClass: { + // // Revised proposal from David Vandervoorde, 2010.07.15. Out << 'L'; assert(isa(E->getType())); @@ -4634,21 +4760,25 @@ recurse: } case Expr::GNUNullExprClass: + // // Mangle as if an integer literal 0. mangleIntegerLiteral(E->getType(), llvm::APSInt(32)); break; case Expr::CXXNullPtrLiteralExprClass: { + // Out << "LDnE"; break; } case Expr::PackExpansionExprClass: + NotPrimaryExpr(); Out << "sp"; mangleExpression(cast(E)->getPattern()); break; case Expr::SizeOfPackExprClass: { + NotPrimaryExpr(); auto *SPE = cast(E); if (SPE->isPartiallySubstituted()) { Out << "sP"; @@ -4673,12 +4803,12 @@ recurse: break; } - case Expr::MaterializeTemporaryExprClass: { - mangleExpression(cast(E)->getSubExpr()); - break; - } + case Expr::MaterializeTemporaryExprClass: + E = cast(E)->getSubExpr(); + goto recurse; case Expr::CXXFoldExprClass: { + NotPrimaryExpr(); auto *FE = cast(E); if (FE->isLeftFold()) Out << (FE->getInit() ? "fL" : "fl"); @@ -4700,27 +4830,34 @@ recurse: } case Expr::CXXThisExprClass: + NotPrimaryExpr(); Out << "fpT"; break; case Expr::CoawaitExprClass: // FIXME: Propose a non-vendor mangling. + NotPrimaryExpr(); Out << "v18co_await"; mangleExpression(cast(E)->getOperand()); break; case Expr::DependentCoawaitExprClass: // FIXME: Propose a non-vendor mangling. + NotPrimaryExpr(); Out << "v18co_await"; mangleExpression(cast(E)->getOperand()); break; case Expr::CoyieldExprClass: // FIXME: Propose a non-vendor mangling. + NotPrimaryExpr(); Out << "v18co_yield"; mangleExpression(cast(E)->getOperand()); break; } + + if (AsTemplateArg && !IsPrimaryExpr) + Out << 'E'; } /// Mangle an expression which refers to a parameter variable. @@ -4970,26 +5107,9 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { Out << "Dp"; mangleType(A.getAsTemplateOrTemplatePattern()); break; - case TemplateArgument::Expression: { - // It's possible to end up with a DeclRefExpr here in certain - // dependent cases, in which case we should mangle as a - // declaration. - const Expr *E = A.getAsExpr()->IgnoreParenImpCasts(); - if (const DeclRefExpr *DRE = dyn_cast(E)) { - const ValueDecl *D = DRE->getDecl(); - if (isa(D) || isa(D)) { - Out << 'L'; - mangle(D); - Out << 'E'; - break; - } - } - - Out << 'X'; - mangleExpression(E); - Out << 'E'; + case TemplateArgument::Expression: + mangleTemplateArgExpr(A.getAsExpr()); break; - } case TemplateArgument::Integral: mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral()); break; @@ -5044,6 +5164,38 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { } } +void CXXNameMangler::mangleTemplateArgExpr(const Expr *E) { + ASTContext &Ctx = Context.getASTContext(); + if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver11) { + mangleExpression(E, UnknownArity, /*AsTemplateArg=*/true); + return; + } + + // Prior to Clang 12, we didn't omit the X .. E around + // correctly in cases where the template argument was + // constructed from an expression rather than an already-evaluated + // literal. In such a case, we would then e.g. emit 'XLi0EE' instead of + // 'Li0E'. + // + // We did special-case DeclRefExpr to attempt to DTRT for that one + // expression-kind, but while doing so, unfortunately handled ParmVarDecl + // (subtype of VarDecl) _incorrectly_, and emitted 'L_Z .. E' instead of + // the proper 'Xfp_E'. + E = E->IgnoreParenImpCasts(); + if (const DeclRefExpr *DRE = dyn_cast(E)) { + const ValueDecl *D = DRE->getDecl(); + if (isa(D) || isa(D)) { + Out << 'L'; + mangle(D); + Out << 'E'; + return; + } + } + Out << 'X'; + mangleExpression(E); + Out << 'E'; +} + /// Determine whether a given value is equivalent to zero-initialization for /// the purpose of discarding a trailing portion of a 'tl' mangling. /// diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index f9f9fe985b6f9e16ffdbaeaccf3f1cad33897228..166aa3b3bd6038a75a0d16de38400913cb21b0e2 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/Mangle.h" #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" @@ -64,6 +65,19 @@ public: } }; +class MSHIPNumberingContext : public MicrosoftNumberingContext { + std::unique_ptr DeviceCtx; + +public: + MSHIPNumberingContext(MangleContext *DeviceMangler) { + DeviceCtx = createItaniumNumberingContext(DeviceMangler); + } + + unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { + return DeviceCtx->getManglingNumber(CallOperator); + } +}; + class MicrosoftCXXABI : public CXXABI { ASTContext &Context; llvm::SmallDenseMap RecordToCopyCtor; @@ -73,8 +87,20 @@ class MicrosoftCXXABI : public CXXABI { llvm::SmallDenseMap UnnamedTagDeclToTypedefNameDecl; + // MangleContext for device numbering context, which is based on Itanium C++ + // ABI. + std::unique_ptr DeviceMangler; + public: - MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } + MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { + if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) { + assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && + Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() && + "Unexpected combination of C++ ABIs."); + DeviceMangler.reset( + Context.createMangleContext(Context.getAuxTargetInfo())); + } + } MemberPointerInfo getMemberPointerInfo(const MemberPointerType *MPT) const override; @@ -133,6 +159,10 @@ public: std::unique_ptr createMangleNumberingContext() const override { + if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) { + assert(DeviceMangler && "Missing device mangler"); + return std::make_unique(DeviceMangler.get()); + } return std::make_unique(); } }; @@ -266,4 +296,3 @@ CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { return new MicrosoftCXXABI(Ctx); } - diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 83821ea6f5fcaf2634e79b3d1fe0ced6d93e1900..917bdf43cc274f8da9edb8169742bc535879274c 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -362,8 +362,9 @@ int64_t Stmt::getID(const ASTContext &Context) const { } CompoundStmt::CompoundStmt(ArrayRef Stmts, SourceLocation LB, - SourceLocation RB) - : Stmt(CompoundStmtClass), RBraceLoc(RB) { + SourceLocation RB, SafeScopeSpecifier SafeSpec, + SourceLocation SafeLoc) + : Stmt(CompoundStmtClass), RBraceLoc(RB), SafeSpec(SafeSpec), SafeLoc(SafeLoc) { CompoundStmtBits.NumStmts = Stmts.size(); setStmts(Stmts); CompoundStmtBits.LBraceLoc = LB; @@ -377,10 +378,11 @@ void CompoundStmt::setStmts(ArrayRef Stmts) { } CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef Stmts, - SourceLocation LB, SourceLocation RB) { + SourceLocation LB, SourceLocation RB, + SafeScopeSpecifier SafeSpec, SourceLocation SafeLoc) { void *Mem = C.Allocate(totalSizeToAlloc(Stmts.size()), alignof(CompoundStmt)); - return new (Mem) CompoundStmt(Stmts, LB, RB); + return new (Mem) CompoundStmt(Stmts, LB, RB, SafeSpec, SafeLoc); } CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e3132752546fe2ff1f77b54c99eaf48999ed7425..d881af09d2667f6c890a3e017b21955f072791f8 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1600,6 +1600,12 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { if (D->isTrivial()) OS << " trivial"; + if (D->getSafeSpecifier() == SS_Safe) { + OS << " safe"; + } else if (D->getSafeSpecifier() == SS_Unsafe) { + OS << " unsafe"; + } + if (const auto *FPT = D->getType()->getAs()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); switch (EPI.ExceptionSpec.Type) { diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 8ddd3c87e09dbb347b92156623e22cb4f681288e..69957a952d17cb5bd7a7dda9361a6a4499ac4928 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -243,10 +243,14 @@ public: return true; ScopedIncrement ScopedDepth(&CurrentDepth); if (auto *Init = Node->getInit()) - if (!match(*Init)) + if (!traverse(*Init)) return false; - if (!match(*Node->getLoopVariable()) || !match(*Node->getRangeInit()) || - !match(*Node->getBody())) + if (!match(*Node->getLoopVariable())) + return false; + if (match(*Node->getRangeInit())) + if (!VisitorBase::TraverseStmt(Node->getRangeInit())) + return false; + if (!match(*Node->getBody())) return false; return VisitorBase::TraverseStmt(Node->getBody()); } @@ -291,7 +295,7 @@ public: if (!match(*Node->getBody())) return false; - return true; + return VisitorBase::TraverseStmt(Node->getBody()); } bool shouldVisitTemplateInstantiations() const { return true; } @@ -488,15 +492,21 @@ public: bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) { if (auto *RF = dyn_cast(S)) { - for (auto *SubStmt : RF->children()) { - if (SubStmt == RF->getInit() || SubStmt == RF->getLoopVarStmt() || - SubStmt == RF->getRangeInit() || SubStmt == RF->getBody()) { - TraverseStmt(SubStmt, Queue); - } else { - ASTNodeNotSpelledInSourceScope RAII(this, true); - TraverseStmt(SubStmt, Queue); + { + ASTNodeNotAsIsSourceScope RAII(this, true); + TraverseStmt(RF->getInit()); + // Don't traverse under the loop variable + match(*RF->getLoopVariable()); + TraverseStmt(RF->getRangeInit()); + } + { + ASTNodeNotSpelledInSourceScope RAII(this, true); + for (auto *SubStmt : RF->children()) { + if (SubStmt != RF->getBody()) + TraverseStmt(SubStmt); } } + TraverseStmt(RF->getBody()); return true; } else if (auto *RBO = dyn_cast(S)) { { @@ -556,9 +566,9 @@ public: if (LE->hasExplicitResultType()) TraverseTypeLoc(Proto.getReturnLoc()); TraverseStmt(LE->getTrailingRequiresClause()); - - TraverseStmt(LE->getBody()); } + + TraverseStmt(LE->getBody()); return true; } return RecursiveASTVisitor::dataTraverseNode(S, Queue); @@ -697,6 +707,10 @@ public: bool shouldVisitTemplateInstantiations() const { return true; } bool shouldVisitImplicitCode() const { return true; } + // We visit the lambda body explicitly, so instruct the RAV + // to not visit it on our behalf too. + bool shouldVisitLambdaBody() const { return false; } + bool IsMatchingInASTNodeNotSpelledInSource() const override { return TraversingASTNodeNotSpelledInSource; } @@ -823,6 +837,14 @@ private: if (EnableCheckProfiling) Timer.setBucket(&TimeByBucket[MP.second->getID()]); BoundNodesTreeBuilder Builder; + + { + TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind()); + if (getASTContext().getParentMapContext().traverseIgnored(DynNode) != + DynNode) + continue; + } + if (MP.first.matches(DynNode, this, &Builder)) { MatchVisitor Visitor(ActiveASTContext, MP.second); Builder.visitMatches(&Visitor); diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 6c7e14e3499aff1900b7639047ce8089dd3242f4..705f1cdf3153363ccd47103f876a1b4cde4af0fc 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -732,7 +732,7 @@ const internal::VariadicDynCastAllOfMatcher typeAliasDecl; const internal::VariadicDynCastAllOfMatcher typeAliasTemplateDecl; const internal::VariadicAllOfMatcher decl; -const internal::VariadicAllOfMatcher decompositionDecl; +const internal::VariadicDynCastAllOfMatcher decompositionDecl; const internal::VariadicDynCastAllOfMatcher linkageSpecDecl; const internal::VariadicDynCastAllOfMatcher namedDecl; diff --git a/clang/lib/Basic/ProfileList.cpp b/clang/lib/Basic/ProfileList.cpp index 56bc37a79301ef5f2059e4b39e42cee2a478c157..2cb05c1c3c073c983c986e6ce2671a488d0ada22 100644 --- a/clang/lib/Basic/ProfileList.cpp +++ b/clang/lib/Basic/ProfileList.cpp @@ -82,6 +82,7 @@ static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) { case CodeGenOptions::ProfileCSIRInstr: return "csllvm"; } + llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum"); } llvm::Optional diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index f17134623b8bc9f312b27dbba66761a59c8835ec..735cecdac56141fa5aefdfe7606de55f4372e9c7 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -43,7 +43,8 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = { AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : TargetInfo(Triple), ABI("aapcs") { - if (getTriple().isOSOpenBSD()) { + if (getTriple().isOSOpenBSD() || + getTriple().getEnvironment() == llvm::Triple::GNUILP32) { Int64Type = SignedLongLong; IntMaxType = SignedLongLong; } else { @@ -58,7 +59,8 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, HasLegalHalfType = true; HasFloat16 = true; - if (Triple.isArch64Bit()) + if (Triple.isArch64Bit() && + getTriple().getEnvironment() != llvm::Triple::GNUILP32) LongWidth = LongAlign = PointerWidth = PointerAlign = 64; else LongWidth = LongAlign = PointerWidth = PointerAlign = 32; @@ -212,10 +214,15 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ELF__"); // Target properties. - if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) { + if (!getTriple().isOSWindows() && getTriple().isArch64Bit() && + getTriple().getEnvironment() != llvm::Triple::GNUILP32) { Builder.defineMacro("_LP64"); Builder.defineMacro("__LP64__"); } + if (getTriple().getEnvironment() == llvm::Triple::GNUILP32) { + Builder.defineMacro("_ILP32"); + Builder.defineMacro("__ILP32__"); + } std::string CodeModel = getTargetOpts().CodeModel; if (CodeModel == "default") @@ -741,8 +748,13 @@ void AArch64leTargetInfo::setDataLayout() { resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128"); else resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); - } else - resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); + } else { + if (getTriple().getEnvironment() == llvm::Triple::GNUILP32) + resetDataLayout( + "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); + else + resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); + } } void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, @@ -765,7 +777,11 @@ void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, void AArch64beTargetInfo::setDataLayout() { assert(!getTriple().isOSBinFormatMachO()); - resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); + if (getTriple().getEnvironment() == llvm::Triple::GNUILP32) + resetDataLayout( + "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); + else + resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); } WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index cfede6e6e756a56315a087a7523f74e3155817ee..6c3036836c6dff107597570c83222a9b3a0705fa 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -57,6 +57,7 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector &Features, } else if (Feature == "+pcrelative-memops") { HasPCRelativeMemops = true; } else if (Feature == "+spe" || Feature == "+efpu2") { + HasStrictFP = false; HasSPE = true; LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); @@ -318,9 +319,6 @@ bool PPCTargetInfo::initFeatureMap( .Case("pwr9", true) .Case("pwr8", true) .Default(false); - Features["float128"] = llvm::StringSwitch(CPU) - .Case("pwr9", true) - .Default(false); Features["spe"] = llvm::StringSwitch(CPU) .Case("8548", true) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 0bf02e605740034117ad5160607d52aa5d752e02..786201ea340d2ff3d369089499fdc0ec9292578b 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -150,7 +150,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, } if (HasV) { - Builder.defineMacro("__riscv_v", "1000000"); + Builder.defineMacro("__riscv_v", "10000"); Builder.defineMacro("__riscv_vector"); } @@ -191,10 +191,10 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__riscv_zfh", "1000"); if (HasZvamo) - Builder.defineMacro("__riscv_zvamo", "1000000"); + Builder.defineMacro("__riscv_zvamo", "10000"); if (HasZvlsseg) - Builder.defineMacro("__riscv_zvlsseg", "1000000"); + Builder.defineMacro("__riscv_zvlsseg", "10000"); } /// Return true if has this feature, need to sync with handleTargetFeatures. diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 694a8095e3365989e108d608174e345c0acef406..c5ad1c7d2c2e0575423a1034b4d00ae31a9829fa 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -513,10 +513,11 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_K8: case CK_K8SSE3: case CK_x86_64: + defineCPUMacros(Builder, "k8"); + break; case CK_x86_64_v2: case CK_x86_64_v3: case CK_x86_64_v4: - defineCPUMacros(Builder, "k8"); break; case CK_AMDFAM10: defineCPUMacros(Builder, "amdfam10"); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 113541bd5024e66d81ffad59b0f469c775d70d12..10e3820d9657803975576cb3e921d1b72f271628 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -13794,12 +13794,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_reduce_fadd_ps512: { Function *F = CGM.getIntrinsic(Intrinsic::vector_reduce_fadd, Ops[1]->getType()); + Builder.getFastMathFlags().setAllowReassoc(true); return Builder.CreateCall(F, {Ops[0], Ops[1]}); } case X86::BI__builtin_ia32_reduce_fmul_pd512: case X86::BI__builtin_ia32_reduce_fmul_ps512: { Function *F = CGM.getIntrinsic(Intrinsic::vector_reduce_fmul, Ops[1]->getType()); + Builder.getFastMathFlags().setAllowReassoc(true); return Builder.CreateCall(F, {Ops[0], Ops[1]}); } case X86::BI__builtin_ia32_reduce_mul_d512: diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 33a2d6f4483ec4dca7c21da600d47773ca62d4ea..e03631a7243a14b45f7eccff91626eb9d36633d4 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -184,6 +184,14 @@ CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM) CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy)); VoidPtrTy = cast(Types.ConvertType(Ctx.VoidPtrTy)); VoidPtrPtrTy = VoidPtrTy->getPointerTo(); + if (CGM.getContext().getAuxTargetInfo()) { + // If the host and device have different C++ ABIs, mark it as the device + // mangle context so that the mangling needs to retrieve the additonal + // device lambda mangling number instead of the regular host one. + DeviceMC->setDeviceMangleContext( + CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() && + CGM.getContext().getAuxTargetInfo()->getCXXABI().isItaniumFamily()); + } } llvm::FunctionCallee CGNVCUDARuntime::getSetupArgumentFn() const { diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 42801372189b171d8aed4ba82e84622fc25f9ee2..bc7582c679894a0591d6d0b6937fddf5e0a4dcba 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1995,9 +1995,14 @@ void CodeGenModule::ConstructAttributeList( if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadNone); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'const' functions have greater restrictions than + // 'pure' functions, so they also cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'pure' functions cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 60ea1b2af037f577ca5f2073cc95a037f17eec22..f3ab91559d30252f427157083562d19d3c5a9c6f 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -2056,7 +2056,7 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, Record->hasTrivialCopyAssignment() || Record->hasTrivialMoveConstructor() || Record->hasTrivialMoveAssignment() || - Record->isUnion()) && + Record->hasAttr() || Record->isUnion()) && "Trying to aggregate-copy a type without a trivial copy/move " "constructor or assignment operator"); // Ignore empty classes in C++. diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 57cc2d60e2af044de9c975068d228ad5e9fd3742..caa5291ff6fa9a63b404ef8637721a622956015b 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -409,6 +409,7 @@ class InlinedOpenMPRegionRAII { llvm::DenseMap LambdaCaptureFields; FieldDecl *LambdaThisCaptureField = nullptr; const CodeGen::CGBlockInfo *BlockInfo = nullptr; + bool NoInheritance = false; public: /// Constructs region for combined constructs. @@ -416,16 +417,19 @@ public: /// a list of functions used for code generation of implicitly inlined /// regions. InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind, bool HasCancel) - : CGF(CGF) { + OpenMPDirectiveKind Kind, bool HasCancel, + bool NoInheritance = true) + : CGF(CGF), NoInheritance(NoInheritance) { // Start emission for the construct. CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); - std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); - LambdaThisCaptureField = CGF.LambdaThisCaptureField; - CGF.LambdaThisCaptureField = nullptr; - BlockInfo = CGF.BlockInfo; - CGF.BlockInfo = nullptr; + if (NoInheritance) { + std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); + LambdaThisCaptureField = CGF.LambdaThisCaptureField; + CGF.LambdaThisCaptureField = nullptr; + BlockInfo = CGF.BlockInfo; + CGF.BlockInfo = nullptr; + } } ~InlinedOpenMPRegionRAII() { @@ -434,9 +438,11 @@ public: cast(CGF.CapturedStmtInfo)->getOldCSI(); delete CGF.CapturedStmtInfo; CGF.CapturedStmtInfo = OldCSI; - std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); - CGF.LambdaThisCaptureField = LambdaThisCaptureField; - CGF.BlockInfo = BlockInfo; + if (NoInheritance) { + std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); + CGF.LambdaThisCaptureField = LambdaThisCaptureField; + CGF.BlockInfo = BlockInfo; + } } }; @@ -3853,7 +3859,7 @@ static void emitPrivatesInit(CodeGenFunction &CGF, // Processing for implicitly captured variables. InlinedOpenMPRegionRAII Region( CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, - /*HasCancel=*/false); + /*HasCancel=*/false, /*NoInheritance=*/true); SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); } if (Type->isArrayType()) { @@ -6214,7 +6220,9 @@ void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, bool HasCancel) { if (!CGF.HaveInsertPoint()) return; - InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); + InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel, + InnerKind != OMPD_critical && + InnerKind != OMPD_master); CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); } @@ -9892,7 +9900,7 @@ void CGOpenMPRuntime::emitTargetNumIterationsCall( llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( - CGM.getModule(), OMPRTL___kmpc_push_target_tripcount), + CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), Args); } }; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8eb7adbc8fcb4a1905ba962479a23a7c2f5fac30..95c0b7b4d7c09cca999a127eb245d28fa5735fdb 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -507,12 +507,23 @@ public: /// True if the C++ Standard Requires Progress. bool CPlusPlusWithProgress() { + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Never) + return false; + return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 || getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20; } /// True if the C Standard Requires Progress. bool CWithProgress() { + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Always) + return true; + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Never) + return false; + return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x; } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 31afbc6b4262876bda2b9fb7880cb64acc42a6c4..9c9bd4e374af7bfd6026d864ca12c78f51ed83ea 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6215,15 +6215,17 @@ llvm::SanitizerStatReport &CodeGenModule::getSanStats() { return *SanStats; } + llvm::Value * CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF) { llvm::Constant *C = ConstantEmitter(CGF).emitAbstract(E, E->getType()); - auto SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr()); - auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false); - return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy, - "__translate_sampler_initializer"), - {C}); + auto *SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr()); + auto *FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false); + auto *Call = CGF.Builder.CreateCall( + CreateRuntimeFunction(FTy, "__translate_sampler_initializer"), {C}); + Call->setCallingConv(Call->getCalledFunction()->getCallingConv()); + return Call; } CharUnits CodeGenModule::getNaturalPointeeTypeAlignment( diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index ffae47e5672ed2962160a092ee674d56528f303b..c7f2a3ea5e0238e5143d1d146c140711a321cde0 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -63,7 +63,7 @@ isExperimentalExtension(StringRef Ext) { Ext == "zbr" || Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc") return RISCVExtensionVersion{"0", "93"}; if (Ext == "v" || Ext == "zvamo" || Ext == "zvlsseg") - return RISCVExtensionVersion{"1", "0"}; + return RISCVExtensionVersion{"0", "10"}; if (Ext == "zfh") return RISCVExtensionVersion{"0", "1"}; return None; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index fdb8a58cd1b341bbcc4103e7333a08f1dd1ddc5e..1976b48e0f6a4aaab5c84358a99604d5c2b033ae 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4669,20 +4669,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - if (Triple.isOSAIX() && Args.hasArg(options::OPT_maltivec)) { - if (Args.getLastArg(options::OPT_mabi_EQ_vec_extabi)) { - CmdArgs.push_back("-mabi=vec-extabi"); - } else { - D.Diag(diag::err_aix_default_altivec_abi); - } - } - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ_vec_extabi, options::OPT_mabi_EQ_vec_default)) { if (!Triple.isOSAIX()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << RawTriple.str(); - if (A->getOption().getID() == options::OPT_mabi_EQ_vec_default) + if (A->getOption().getID() == options::OPT_mabi_EQ_vec_extabi) + CmdArgs.push_back("-mabi=vec-extabi"); + else D.Diag(diag::err_aix_default_altivec_abi); } @@ -5626,6 +5620,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (A->getOption().matches(options::OPT_freroll_loops)) CmdArgs.push_back("-freroll-loops"); + Args.AddLastArg(CmdArgs, options::OPT_ffinite_loops, + options::OPT_fno_finite_loops); + Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_funroll_loops, options::OPT_fno_unroll_loops); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 6a95aa5ec62878cc88645caa7745834fa42d71ba..bcaea71dca9436b566647d7caf9504e48fd37c0f 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -605,6 +605,11 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back("-plugin-opt=new-pass-manager"); } + // Pass an option to enable pseudo probe emission. + if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling, + options::OPT_fno_pseudo_probe_for_profiling, false)) + CmdArgs.push_back("-plugin-opt=pseudo-probe-for-profiling"); + // Setup statistics file output. SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D); if (!StatsFile.empty()) diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index e17a6bd4bdd25cbe771176b801b7d14c3b503437..9663a7390ada725a7540b68213dd0d4d58df7ed5 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -236,15 +236,6 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) ExtraOpts.push_back("relro"); } - if (Triple.isAndroid() && Triple.isAndroidVersionLT(29)) { - // https://github.com/android/ndk/issues/1196 - // The unwinder used by the crash handler on versions of Android prior to - // API 29 did not correctly handle binaries built with rosegment, which is - // enabled by default for LLD. Android only supports LLD, so it's not an - // issue that this flag is not accepted by other linkers. - ExtraOpts.push_back("--no-rosegment"); - } - // Android ARM/AArch64 use max-page-size=4096 to reduce VMA usage. Note, lld // from 11 onwards default max-page-size to 65536 for both ARM and AArch64. if ((Triple.isARM() || Triple.isAArch64()) && Triple.isAndroid()) { diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index f4b7a57e0bb709be7a2f1529fca96e7877966abc..13943b6c404a9b6fa4a0bd4ebd00905cc999149b 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -11,6 +11,7 @@ #include "Darwin.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Version.h" +#include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" @@ -520,7 +521,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, // translate 'lld' into 'lld-link', and in the case of the regular msvc // linker, we need to use a special search algorithm. llvm::SmallString<128> linkPath; - StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link"); + StringRef Linker + = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); + if (Linker.empty()) + Linker = "link"; if (Linker.equals_lower("lld")) Linker = "lld-link"; diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index f155d74632f93c4951007af7f21ba3069ec89679..e162165b25613118e81596959b63ca6920e3973c 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -296,6 +296,7 @@ void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args, CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++"); CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi"); + CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread"); } std::string OpenBSD::getCompilerRT(const ArgList &Args, diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 34c291ecc492c844e0e4bae3e62f784a44137225..82d6cfed308d690f14f824178b12ad66211d0ff7 100755 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1917,12 +1917,12 @@ private: if (Tok.Next->isOneOf(tok::identifier, tok::kw_this)) return true; - if (Tok.Next->is(tok::l_paren) && - !(Tok.Previous && Tok.Previous->is(tok::identifier) && - Tok.Previous->Previous && - Tok.Previous->Previous->isOneOf(tok::arrowstar, tok::arrow, - tok::star))) - return true; + // Look for a cast `( x ) (`. + if (Tok.Next->is(tok::l_paren) && Tok.Previous && Tok.Previous->Previous) { + if (Tok.Previous->is(tok::identifier) && + Tok.Previous->Previous->is(tok::l_paren)) + return true; + } if (!Tok.Next->Next) return false; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index d1138bbc9c36ff6afd7a2bcc7a2e198093d166ab..7d197310e65bb815bd882fc9a2f1a07d2026021d 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -371,7 +371,7 @@ private: if (Previous->is(tok::comment)) Previous = Previous->getPreviousNonComment(); if (Previous) { - if (Previous->is(tok::greater)) + if (Previous->is(tok::greater) && !I[-1]->InPPDirective) return 0; if (Previous->is(tok::identifier)) { const FormatToken *PreviousPrevious = @@ -1281,13 +1281,6 @@ void UnwrappedLineFormatter::formatFirstToken( if (Newlines) Indent = NewlineIndent; - // If in Whitemsmiths mode, indent start and end of blocks - if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) { - if (RootToken.isOneOf(tok::l_brace, tok::r_brace, tok::kw_case, - tok::kw_default)) - Indent += Style.IndentWidth; - } - // Preprocessor directives get indented before the hash only if specified if (Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash && (Line.Type == LT_PreprocessorDirective || diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index f689a6361a3ad9e538db4eed0d7bb266555d47e8..bec18bd5d8df4bd8780eac7adb44572a1fd38cc7 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -579,17 +579,23 @@ size_t UnwrappedLineParser::computePPHash() const { return h; } -void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, - bool MunchSemi) { +void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels, + bool MunchSemi, + bool UnindentWhitesmithsBraces) { assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) && "'{' or macro block token expected"); const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin); FormatTok->setBlockKind(BK_Block); + // For Whitesmiths mode, jump to the next level prior to skipping over the + // braces. + if (AddLevels > 0 && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) + ++Line->Level; + size_t PPStartHash = computePPHash(); unsigned InitialLevel = Line->Level; - nextToken(/*LevelDifference=*/AddLevel ? 1 : 0); + nextToken(/*LevelDifference=*/AddLevels); if (MacroBlock && FormatTok->is(tok::l_paren)) parseParens(); @@ -602,10 +608,16 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, ? (UnwrappedLine::kInvalidIndex) : (CurrentLines->size() - 1 - NbPreprocessorDirectives); + // Whitesmiths is weird here. The brace needs to be indented for the namespace + // block, but the block itself may not be indented depending on the style + // settings. This allows the format to back up one level in those cases. + if (UnindentWhitesmithsBraces) + --Line->Level; + ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, MustBeDeclaration); - if (AddLevel) - ++Line->Level; + if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths) + Line->Level += AddLevels; parseLevel(/*HasOpeningBrace=*/true); if (eof()) @@ -621,7 +633,7 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, size_t PPEndHash = computePPHash(); // Munch the closing brace. - nextToken(/*LevelDifference=*/AddLevel ? -1 : 0); + nextToken(/*LevelDifference=*/-AddLevels); if (MacroBlock && FormatTok->is(tok::l_paren)) parseParens(); @@ -637,6 +649,7 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, nextToken(); Line->Level = InitialLevel; + FormatTok->setBlockKind(BK_Block); if (PPStartHash == PPEndHash) { Line->MatchingOpeningBlockLineIndex = OpeningLineIndex; @@ -2128,15 +2141,34 @@ void UnwrappedLineParser::parseNamespace() { if (ShouldBreakBeforeBrace(Style, InitialToken)) addUnwrappedLine(); - bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All || - (Style.NamespaceIndentation == FormatStyle::NI_Inner && - DeclarationScopeStack.size() > 1); - parseBlock(/*MustBeDeclaration=*/true, AddLevel); + unsigned AddLevels = + Style.NamespaceIndentation == FormatStyle::NI_All || + (Style.NamespaceIndentation == FormatStyle::NI_Inner && + DeclarationScopeStack.size() > 1) + ? 1u + : 0u; + bool ManageWhitesmithsBraces = + AddLevels == 0u && + Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; + + // If we're in Whitesmiths mode, indent the brace if we're not indenting + // the whole block. + if (ManageWhitesmithsBraces) + ++Line->Level; + + parseBlock(/*MustBeDeclaration=*/true, AddLevels, + /*MunchSemi=*/true, + /*UnindentWhitesmithsBraces=*/ManageWhitesmithsBraces); + // Munch the semicolon after a namespace. This is more common than one would // think. Putting the semicolon into its own line is very ugly. if (FormatTok->Tok.is(tok::semi)) nextToken(); - addUnwrappedLine(); + + addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep); + + if (ManageWhitesmithsBraces) + --Line->Level; } // FIXME: Add error handling. } @@ -2222,6 +2254,11 @@ void UnwrappedLineParser::parseDoWhile() { return; } + // If in Whitesmiths mode, the line with the while() needs to be indented + // to the same level as the block. + if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) + ++Line->Level; + nextToken(); parseStructuralElement(); } @@ -2234,25 +2271,19 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) { if (LeftAlignLabel) Line->Level = 0; - bool RemoveWhitesmithsCaseIndent = - (!Style.IndentCaseBlocks && - Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths); - - if (RemoveWhitesmithsCaseIndent) - --Line->Level; - if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) { - CompoundStatementIndenter Indenter( - this, Line->Level, Style.BraceWrapping.AfterCaseLabel, - Style.BraceWrapping.IndentBraces || RemoveWhitesmithsCaseIndent); + CompoundStatementIndenter Indenter(this, Line->Level, + Style.BraceWrapping.AfterCaseLabel, + Style.BraceWrapping.IndentBraces); parseBlock(/*MustBeDeclaration=*/false); if (FormatTok->Tok.is(tok::kw_break)) { if (Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Always) { addUnwrappedLine(); - if (RemoveWhitesmithsCaseIndent) { + if (!Style.IndentCaseBlocks && + Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) { Line->Level++; } } @@ -2920,17 +2951,29 @@ LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line, llvm::dbgs() << "\n"; } -void UnwrappedLineParser::addUnwrappedLine() { +void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { if (Line->Tokens.empty()) return; LLVM_DEBUG({ if (CurrentLines == &Lines) printDebugInfo(*Line); }); + + // If this line closes a block when in Whitesmiths mode, remember that + // information so that the level can be decreased after the line is added. + // This has to happen after the addition of the line since the line itself + // needs to be indented. + bool ClosesWhitesmithsBlock = + Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex && + Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; + CurrentLines->push_back(std::move(*Line)); Line->Tokens.clear(); Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex; Line->FirstStartColumn = 0; + + if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove) + --Line->Level; if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) { CurrentLines->append( std::make_move_iterator(PreprocessorDirectives.begin()), diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 02b328cb72de65b9be7f150301da2266c81e560e..ce135fac5e578ac174f734501b7235950e6d7e75 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -85,8 +85,9 @@ private: void reset(); void parseFile(); void parseLevel(bool HasOpeningBrace); - void parseBlock(bool MustBeDeclaration, bool AddLevel = true, - bool MunchSemi = true); + void parseBlock(bool MustBeDeclaration, unsigned AddLevels = 1u, + bool MunchSemi = true, + bool UnindentWhitesmithsBraces = false); void parseChildBlock(); void parsePPDirective(); void parsePPDefine(); @@ -140,7 +141,12 @@ private: bool tryToParsePropertyAccessor(); void tryToParseJSFunction(); bool tryToParseSimpleAttribute(); - void addUnwrappedLine(); + + // Used by addUnwrappedLine to denote whether to keep or remove a level + // when resetting the line state. + enum class LineLevel { Remove, Keep }; + + void addUnwrappedLine(LineLevel AdjustLevel = LineLevel::Remove); bool eof() const; // LevelDifference is the difference of levels after and before the current // token. For example: diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d8be4ea14868d1042195874a9ba2f369e7d67783..5c5cf46150e2786fa58639f24afab8cccff12d54 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1037,7 +1037,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, (Opts.OptimizationLevel > 1)); - Opts.BinutilsVersion = std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ)); @@ -1324,6 +1323,10 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); + if (Args.hasArg(options::OPT_ffinite_loops)) + Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always; + else if (Args.hasArg(options::OPT_fno_finite_loops)) + Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never; return Success; } @@ -2470,6 +2473,8 @@ void CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, bool IsTargetSpecified = Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ); + Opts.ConvergentFunctions = Opts.ConvergentFunctions || Opts.OpenMPIsDevice; + if (Opts.OpenMP || Opts.OpenMPSimd) { if (int Version = getLastArgIntValue( Args, OPT_fopenmp_version_EQ, diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index d47ad1b74649ec005959ed6677edd9176ea3aaf0..c64a912ce919d878de31301f555c6c04e029b084 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -565,7 +565,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_aggregate_bases", "201603L"); Builder.defineMacro("__cpp_structured_bindings", "201606L"); Builder.defineMacro("__cpp_nontype_template_args", - LangOpts.CPlusPlus20 ? "201911L" : "201411L"); + "201411L"); // (not latest) Builder.defineMacro("__cpp_fold_expressions", "201603L"); Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L"); Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L"); diff --git a/clang/lib/Headers/avx512fintrin.h b/clang/lib/Headers/avx512fintrin.h index 2ee4350b14d4368c2b57105f0eec8ad98c99bb96..f226382cbb2c685e64f54b1962d2961aa8eefd6b 100644 --- a/clang/lib/Headers/avx512fintrin.h +++ b/clang/lib/Headers/avx512fintrin.h @@ -9297,9 +9297,12 @@ _mm512_mask_abs_pd(__m512d __W, __mmask8 __K, __m512d __A) /* Vector-reduction arithmetic accepts vectors as inputs and produces scalars as * outputs. This class of vector operation forms the basis of many scientific - * computations. In vector-reduction arithmetic, the evaluation off is + * computations. In vector-reduction arithmetic, the evaluation order is * independent of the order of the input elements of V. + * For floating point types, we always assume the elements are reassociable even + * if -fast-math is off. + * Used bisection method. At each step, we partition the vector with previous * step in half, and the operation is performed on its two halves. * This takes log2(n) steps where n is the number of elements in the vector. @@ -9345,8 +9348,11 @@ _mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) { return __builtin_ia32_reduce_or_q512(__W); } +// -0.0 is used to ignore the start value since it is the neutral value of +// floating point addition. For more information, please refer to +// https://llvm.org/docs/LangRef.html#llvm-vector-reduce-fadd-intrinsic static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_add_pd(__m512d __W) { - return __builtin_ia32_reduce_fadd_pd512(0.0, __W); + return __builtin_ia32_reduce_fadd_pd512(-0.0, __W); } static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_pd(__m512d __W) { @@ -9356,7 +9362,7 @@ static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_pd(__m512d __W) static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) { __W = _mm512_maskz_mov_pd(__M, __W); - return __builtin_ia32_reduce_fadd_pd512(0.0, __W); + return __builtin_ia32_reduce_fadd_pd512(-0.0, __W); } static __inline__ double __DEFAULT_FN_ATTRS512 @@ -9411,7 +9417,7 @@ _mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) { static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_reduce_add_ps(__m512 __W) { - return __builtin_ia32_reduce_fadd_ps512(0.0f, __W); + return __builtin_ia32_reduce_fadd_ps512(-0.0f, __W); } static __inline__ float __DEFAULT_FN_ATTRS512 @@ -9422,7 +9428,7 @@ _mm512_reduce_mul_ps(__m512 __W) { static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W) { __W = _mm512_maskz_mov_ps(__M, __W); - return __builtin_ia32_reduce_fadd_ps512(0.0f, __W); + return __builtin_ia32_reduce_fadd_ps512(-0.0f, __W); } static __inline__ float __DEFAULT_FN_ATTRS512 diff --git a/clang/lib/Headers/ppc_wrappers/xmmintrin.h b/clang/lib/Headers/ppc_wrappers/xmmintrin.h index 0f429fa0408116b1c45d0dbbd7399ecd778e9fe7..0e45b96769f879a31a4555db35312e5386351f5c 100644 --- a/clang/lib/Headers/ppc_wrappers/xmmintrin.h +++ b/clang/lib/Headers/ppc_wrappers/xmmintrin.h @@ -28,7 +28,7 @@ Most SSE scalar float intrinsic operations can be performed more efficiently as C language float scalar operations or optimized to use vector SIMD operations. We recommend this for new applications. */ -#error "Please read comment above. Use -DNO_WARN_X86_INTRINSICS to disable this error." +#error "Please read comment above. Use -DNO_WARN_X86_INTRINSICS to disable this error." #endif #ifndef _XMMINTRIN_H_INCLUDED @@ -62,14 +62,13 @@ /* The Intel API is flexible enough that we must allow aliasing with other vector types, and their scalar components. */ -typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef vector float __m128 __attribute__((__may_alias__)); /* Unaligned version of the same type. */ -typedef float __m128_u __attribute__ ((__vector_size__ (16), __may_alias__, - __aligned__ (1))); +typedef vector float __m128_u __attribute__((__may_alias__, __aligned__(1))); /* Internal data types for implementing the intrinsics. */ -typedef float __v4sf __attribute__ ((__vector_size__ (16))); +typedef vector float __v4sf; /* Create an undefined vector. */ extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 94f1ce91f88444fde639cc8af0b9945af9c4de59..177786d903907aabca30d2994f83fc806af65eb7 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -119,12 +119,8 @@ Preprocessor::Preprocessor(std::shared_ptr PPOpts, // 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().CPlusPlus20) { - (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); - SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); - } else { - Ident__VA_OPT__ = nullptr; - } + (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); // Initialize the pragma handlers. RegisterBuiltinPragmas(); diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 97cb2cf0bb8c2291ab4a6a22e0a650dca6ed530e..da5681aaf4784fd95d35c39178e240fae2dc040c 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -148,12 +148,12 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( return false; // GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if - // __VA_ARGS__ is empty, but not in strict mode where there are no - // named arguments, where it remains. With GNU extensions, it is removed - // regardless of named arguments. + // __VA_ARGS__ is empty, but not in strict C99 mode where there are no + // named arguments, where it remains. In all other modes, including C99 + // with GNU extensions, it is removed regardless of named arguments. // Microsoft also appears to support this extension, unofficially. - if (!PP.getLangOpts().GNUMode && !PP.getLangOpts().MSVCCompat && - Macro->getNumParams() < 2) + if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode + && Macro->getNumParams() < 2) return false; // Is a comma available to be removed? diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 571164139630ac21c4a985dcee70ddb5e1a9a6ac..4ce90b17819113ee9916b1c1a163666c243db944 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2486,7 +2486,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, static bool isValidAfterIdentifierInDeclarator(const Token &T) { return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi, tok::comma, tok::equal, tok::kw_asm, tok::l_brace, - tok::colon); + tok::colon, tok::kw___Safe__, tok::kw___Unsafe__); } /// ParseImplicitInt - This method is called when we have an non-typename @@ -3899,6 +3899,22 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, PrevSpec, DiagID, Policy); break; + // safe-specifier: + case tok::kw___Safe__: + case tok::kw___Unsafe__: { + if (GetLookAheadToken(1).is(tok::l_square)) { + goto DoneWithDeclSpec; + } else if (GetLookAheadToken(1).is(tok::l_brace)) { + break; + } else { + SafeScopeSpecifier SafeSpec = SS_Unsafe; + if (Tok.is(tok::kw___Safe__)) { + SafeSpec = SS_Safe; + } + isInvalid = DS.setFunctionSafeSpecifier(Loc, PrevSpec, DiagID, SafeSpec); + break; + } + } // class-specifier: case tok::kw_class: case tok::kw_struct: @@ -4216,7 +4232,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, } // Parse _Static_assert declaration. - if (Tok.is(tok::kw__Static_assert)) { + if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) { SourceLocation DeclEnd; ParseStaticAssertDeclaration(DeclEnd); continue; @@ -5180,6 +5196,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_friend: // static_assert-declaration + case tok::kw_static_assert: case tok::kw__Static_assert: // GNU typeof support. diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index f9b852826775fc0ace9122894cea2dd95ba6e32a..6008d068e8c16ea2ac0e4355ffec68ac66e7cd56 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -280,6 +280,12 @@ struct PragmaAttributeHandler : public PragmaHandler { ParsedAttributes AttributesForPragmaAttribute; }; +struct PragmaSafeHandler : public PragmaHandler { + PragmaSafeHandler() : PragmaHandler("SAFE") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &FirstToken) override; +}; + struct PragmaMaxTokensHereHandler : public PragmaHandler { PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {} void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, @@ -423,6 +429,9 @@ void Parser::initializePragmaHandlers() { MaxTokensTotalPragmaHandler = std::make_unique(); PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get()); + + SafeHandler.reset(new PragmaSafeHandler()); + PP.AddPragmaHandler(SafeHandler.get()); } void Parser::resetPragmaHandlers() { @@ -539,6 +548,9 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get()); MaxTokensTotalPragmaHandler.reset(); + + PP.RemovePragmaHandler(SafeHandler.get()); + SafeHandler.reset(); } /// Handle the annotation token produced for #pragma unused(...) @@ -1715,6 +1727,14 @@ void Parser::HandlePragmaAttribute() { std::move(SubjectMatchRules)); } +void Parser::HandlePragmaSafe() { + assert(Tok.is(tok::annot_pragma_safe)); + Sema::PragmaSafeStatus St = static_cast( + reinterpret_cast(Tok.getAnnotationValue())); + (void)ConsumeAnnotationToken(); + Actions.ActOnPragmaSafe(St); +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -3650,6 +3670,37 @@ void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false, /*IsReinject=*/false); } +void PragmaSafeHandler::HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &Tok) { + PP.Lex(Tok); + Sema::PragmaSafeStatus St = Sema::PSS_On; + + if (!Tok.is(tok::identifier)) { + return; + } + + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("ON")) + St = Sema::PSS_On; + else if (II->isStr("OFF")) + St = Sema::PSS_Off; + else + return; + + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "SAFE"; + + MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(1), 1); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_safe); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationEndLoc(Tok.getLocation()); + Toks[0].setAnnotationValue( + reinterpret_cast(static_cast(St))); + PP.EnterTokenStream(Toks, true, false); +} + // Handle '#pragma clang max_tokens 12345'. void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 26a02575010c63fa5e0659a93ade18de99005fb5..35d3b4b718db89e4234333bfe00f221d9f928ffc 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -206,6 +206,7 @@ Retry: LLVM_FALLTHROUGH; } +Default: default: { if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != @@ -233,6 +234,14 @@ Retry: return ParseExprStatement(StmtCtx); } + case tok::kw___Safe__: + case tok::kw___Unsafe__: { + Token Next = NextToken(); + if (Next.is(tok::l_brace)) + return ParseCompoundStatement(); + goto Default; + } + case tok::kw___attribute: { GNUAttributeLoc = Tok.getLocation(); ParseGNUAttributes(Attrs); @@ -420,6 +429,10 @@ Retry: case tok::annot_pragma_attribute: HandlePragmaAttribute(); return StmtEmpty(); + + case tok::annot_pragma_safe: + HandlePragmaSafe(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -899,6 +912,18 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { /// StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, unsigned ScopeFlags) { + // Add security scope identification processing. + SafeScopeSpecifier SafeSpec = SS_None; + SourceLocation SafeLoc; + + if (Tok.is(tok::kw___Safe__)) { + SafeSpec = SS_Safe; + SafeLoc = ConsumeToken(); + } else if (Tok.is(tok::kw___Unsafe__)) { + SafeSpec = SS_Unsafe; + SafeLoc = ConsumeToken(); + } + assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); // Enter a scope to hold everything within the compound stmt. Compound @@ -906,7 +931,7 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, ParseScope CompoundScope(this, ScopeFlags); // Parse the statements in the body. - return ParseCompoundStatementBody(isStmtExpr); + return ParseCompoundStatementBody(isStmtExpr, SafeSpec, SafeLoc); } /// Parse any pragmas at the start of the compound expression. We handle these @@ -967,6 +992,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_dump: HandlePragmaDump(); break; + case tok::annot_pragma_safe: + HandlePragmaSafe(); + break; default: checkForPragmas = false; break; @@ -1028,7 +1056,7 @@ StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) { /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope /// stack. -StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { +StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr, SafeScopeSpecifier SafeSpec, SourceLocation SafeLoc) { PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), Tok.getLocation(), "in compound statement ('{}')"); @@ -1159,7 +1187,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { CloseLoc = T.getCloseLocation(); return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc, - Stmts, isStmtExpr); + Stmts, isStmtExpr, SafeSpec, SafeLoc); } /// ParseParenExprOrCondition: diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 9b0f921b426928ab13728859a7e0473a68ca3898..2a42f058b8ec452edad0a8b0167744c61023c39c 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -613,6 +613,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, bool IsFirstDecl) { HandlePragmaUnused(); return false; + case tok::annot_pragma_safe: + HandlePragmaSafe(); + return false; + case tok::kw_export: switch (NextToken().getKind()) { case tok::kw_module: diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index da42db3e8f7b6f4644bf428bc145ffd1d61e72da..d6639e900f7b55fd298fbe9edc8cdc502b61ee22 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -461,7 +461,7 @@ unsigned DeclSpec::getParsedSpecifiers() const { Res |= PQ_TypeSpecifier; if (FS_inline_specified || FS_virtual_specified || hasExplicitSpecifier() || - FS_noreturn_specified || FS_forceinline_specified) + FS_noreturn_specified || FS_forceinline_specified || FS_safe_specified) Res |= PQ_FunctionSpecifier; return Res; } @@ -1057,6 +1057,24 @@ bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc, return false; } +bool DeclSpec::setFunctionSafeSpecifier(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + SafeScopeSpecifier SafeSpec) { + if (FS_safe_specified == SS_None) { + FS_safe_specified = SafeSpec; + FS_safe_loc = Loc; + return false; + } else if (FS_safe_specified == SS_Safe) { + PrevSpec = "safe"; + } else if (FS_safe_specified == SS_Unsafe) { + PrevSpec = "unsafe"; + } else { + PrevSpec = ""; + } + return true; +} + bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (Friend_specified) { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 55cb3aee6194c5f8df1f5c4a97edef94bb3d9423..450f9c020f7feac5dd11f8d6299039bbd604ca03 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -14,6 +14,7 @@ #include "UsedDeclVisitor.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -537,6 +538,13 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { if (E->IgnoreParenImpCasts()->getType()->isNullPtrType()) return; + // Don't diagnose the conversion from a 0 literal to a null pointer argument + // in a synthesized call to operator<=>. + if (!CodeSynthesisContexts.empty() && + CodeSynthesisContexts.back().Kind == + CodeSynthesisContext::RewritingOperatorAsSpaceship) + return; + // If it is a macro from system header, and if the macro name is not "NULL", // do not warn. SourceLocation MaybeMacroLoc = E->getBeginLoc(); @@ -1733,11 +1741,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { } } -Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder +Sema::targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD) { + FD = FD ? FD : getCurFunctionDecl(); if (LangOpts.OpenMP) - return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID) - : diagIfOpenMPHostCode(Loc, DiagID); + return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) + : diagIfOpenMPHostCode(Loc, DiagID, FD); if (getLangOpts().CUDA) return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID) : CUDADiagIfHostCode(Loc, DiagID); @@ -1746,7 +1755,7 @@ Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, return SYCLDiagIfDeviceCode(Loc, DiagID); return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID, - getCurFunctionDecl(), *this); + FD, *this); } Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, @@ -1765,15 +1774,14 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, DiagID, getCurFunctionDecl(), *this); } - SemaDiagnosticBuilder DB = - getLangOpts().CUDAIsDevice - ? CUDADiagIfDeviceCode(Loc, DiagID) - : CUDADiagIfHostCode(Loc, DiagID); + SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice + ? CUDADiagIfDeviceCode(Loc, DiagID) + : CUDADiagIfHostCode(Loc, DiagID); SetIsLastErrorImmediate(DB.isImmediate()); return DB; } -void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { +void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) { if (isUnevaluatedContext()) return; @@ -1791,13 +1799,17 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { return; } + // Try to associate errors with the lexical context, if that is a function, or + // the value declaration otherwise. + FunctionDecl *FD = + isa(C) ? cast(C) : dyn_cast(D); auto CheckType = [&](QualType Ty) { if (Ty->isDependentType()) return; if (Ty->isExtIntType()) { if (!Context.getTargetInfo().hasExtIntType()) { - targetDiag(Loc, diag::err_device_unsupported_type) + targetDiag(Loc, diag::err_device_unsupported_type, FD) << D << false /*show bit size*/ << 0 /*bitsize*/ << Ty << Context.getTargetInfo().getTriple().str(); } @@ -1810,11 +1822,12 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { !Context.getTargetInfo().hasFloat128Type()) || (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 && !Context.getTargetInfo().hasInt128Type())) { - targetDiag(Loc, diag::err_device_unsupported_type) + if (targetDiag(Loc, diag::err_device_unsupported_type, FD) << D << true /*show bit size*/ << static_cast(Context.getTypeSize(Ty)) << Ty - << Context.getTargetInfo().getTriple().str(); - targetDiag(D->getLocation(), diag::note_defined_here) << D; + << Context.getTargetInfo().getTriple().str()) + D->setInvalidDecl(); + targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } }; @@ -1826,6 +1839,8 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { CheckType(ParamTy); CheckType(FPTy->getReturnType()); } + if (const auto *FNPTy = dyn_cast(Ty)) + CheckType(FNPTy->getReturnType()); } /// Looks through the macro-expansion chain for the given diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2d3d36f4adad0df6f755aecbeb78ef19fe375dce..2b55712d44c2757e63f93f3cc7de1e47363a8509 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2623,7 +2623,10 @@ static bool isValidBPFPreserveEnumValueArg(Expr *Arg) { return false; const auto *CE = dyn_cast(UO->getSubExpr()); - if (!CE || CE->getCastKind() != CK_IntegralToPointer) + if (!CE) + return false; + if (CE->getCastKind() != CK_IntegralToPointer && + CE->getCastKind() != CK_NullToPointer) return false; // The integer must be from an EnumConstantDecl. diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index c2785fd60fc26c65acfaf051db256f9d08af1edf..be04970979b388fda328af7d79dc5e45bfed2a84 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5158,6 +5158,20 @@ private: llvm::DenseMap Results; }; + +// If \p Base is ParenListExpr, assume a chain of comma operators and pick the +// last expr. We expect other ParenListExprs to be resolved to e.g. constructor +// calls before here. (So the ParenListExpr should be nonempty, but check just +// in case) +Expr *unwrapParenList(Expr *Base) { + if (auto *PLE = llvm::dyn_cast_or_null(Base)) { + if (PLE->getNumExprs() == 0) + return nullptr; + Base = PLE->getExpr(PLE->getNumExprs() - 1); + } + return Base; +} + } // namespace void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, @@ -5165,6 +5179,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement, QualType PreferredType) { + Base = unwrapParenList(Base); + OtherOpBase = unwrapParenList(OtherOpBase); if (!Base || !CodeCompleter) return; @@ -5597,12 +5613,13 @@ ProduceSignatureHelp(Sema &SemaRef, Scope *S, QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef Args, SourceLocation OpenParLoc) { - if (!CodeCompleter) + Fn = unwrapParenList(Fn); + if (!CodeCompleter || !Fn) return QualType(); // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. - if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args)) + if (Fn->isTypeDependent() || anyNullArguments(Args)) return QualType(); // In presence of dependent args we surface all possible signatures using the // non-dependent args in the prefix. Afterwards we do a post filtering to make diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3ee0c43097d7dd04da615317602eb81f80f1f07c..f311f6796c5fd3b6ba4ab8f811fd580c6b118e81 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8920,6 +8920,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, isVirtualOkay); if (!NewFD) return nullptr; + SafeScopeSpecifier FuncSpec = D.getDeclSpec().getSafeSpecifier(); + if (FuncSpec == SS_None) { + FuncSpec = GetPragmaSafeInfo(); + } + NewFD->setSafeSpecifier(FuncSpec); + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) NewFD->setTopLevelDeclInObjCContainer(); @@ -9420,6 +9426,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) + checkDeviceDecl(NewFD, D.getBeginLoc()); + if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. if (!NewFD->isInvalidDecl() && NewFD->isMain()) @@ -18329,42 +18338,51 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, if (FD->isDependentContext()) return FunctionEmissionStatus::TemplateDiscarded; - FunctionEmissionStatus OMPES = FunctionEmissionStatus::Unknown; + // Check whether this function is an externally visible definition. + auto IsEmittedForExternalSymbol = [this, FD]() { + // We have to check the GVA linkage of the function's *definition* -- if we + // only have a declaration, we don't know whether or not the function will + // be emitted, because (say) the definition could include "inline". + FunctionDecl *Def = FD->getDefinition(); + + return Def && !isDiscardableGVALinkage( + getASTContext().GetGVALinkageForFunction(Def)); + }; + if (LangOpts.OpenMPIsDevice) { + // In OpenMP device mode we will not emit host only functions, or functions + // we don't need due to their linkage. Optional DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl()); - if (DevTy.hasValue()) { + // DevTy may be changed later by + // #pragma omp declare target to(*) device_type(*). + // Therefore DevTyhaving no value does not imply host. The emission status + // will be checked again at the end of compilation unit with Final = true. + if (DevTy.hasValue()) if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host) - OMPES = FunctionEmissionStatus::OMPDiscarded; - else if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any) { - OMPES = FunctionEmissionStatus::Emitted; - } - } - } else if (LangOpts.OpenMP) { - // In OpenMP 4.5 all the functions are host functions. - if (LangOpts.OpenMP <= 45) { - OMPES = FunctionEmissionStatus::Emitted; - } else { - Optional DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl()); - // In OpenMP 5.0 or above, DevTy may be changed later by - // #pragma omp declare target to(*) device_type(*). Therefore DevTy - // having no value does not imply host. The emission status will be - // checked again at the end of compilation unit. - if (DevTy.hasValue()) { - if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { - OMPES = FunctionEmissionStatus::OMPDiscarded; - } else if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any) - OMPES = FunctionEmissionStatus::Emitted; - } else if (Final) - OMPES = FunctionEmissionStatus::Emitted; - } - } - if (OMPES == FunctionEmissionStatus::OMPDiscarded || - (OMPES == FunctionEmissionStatus::Emitted && !LangOpts.CUDA)) - return OMPES; + return FunctionEmissionStatus::OMPDiscarded; + // If we have an explicit value for the device type, or we are in a target + // declare context, we need to emit all extern and used symbols. + if (isInOpenMPDeclareTargetContext() || DevTy.hasValue()) + if (IsEmittedForExternalSymbol()) + return FunctionEmissionStatus::Emitted; + // Device mode only emits what it must, if it wasn't tagged yet and needed, + // we'll omit it. + if (Final) + return FunctionEmissionStatus::OMPDiscarded; + } else if (LangOpts.OpenMP > 45) { + // In OpenMP host compilation prior to 5.0 everything was an emitted host + // function. In 5.0, no_host was introduced which might cause a function to + // be ommitted. + Optional DevTy = + OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl()); + if (DevTy.hasValue()) + if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) + return FunctionEmissionStatus::OMPDiscarded; + } + + if (Final && LangOpts.OpenMP && !LangOpts.CUDA) + return FunctionEmissionStatus::Emitted; if (LangOpts.CUDA) { // When compiling for device, host functions are never emitted. Similarly, @@ -18378,17 +18396,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, (T == Sema::CFT_Device || T == Sema::CFT_Global)) return FunctionEmissionStatus::CUDADiscarded; - // Check whether this function is externally visible -- if so, it's - // known-emitted. - // - // We have to check the GVA linkage of the function's *definition* -- if we - // only have a declaration, we don't know whether or not the function will - // be emitted, because (say) the definition could include "inline". - FunctionDecl *Def = FD->getDefinition(); - - if (Def && - !isDiscardableGVALinkage(getASTContext().GetGVALinkageForFunction(Def)) - && (!LangOpts.OpenMP || OMPES == FunctionEmissionStatus::Emitted)) + if (IsEmittedForExternalSymbol()) return FunctionEmissionStatus::Emitted; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 30d08b3d4ac0e23437ecd07b78d27d5b6955f9f1..8aee02d2f049b2474595e54b07677c990344abfe 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1535,6 +1535,77 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL, return true; } +// EnhanceC +template +static bool checkFunctionTypeIndex( + Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum, + const Expr *IdxExpr, ParamIdx &Idx, const FunctionProtoType *Proto) { + + unsigned NumParams = Proto->getNumParams(); + + Optional IdxInt; + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || + !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) { + S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) + << &AI << AttrArgNum << AANT_ArgumentIntegerConstant + << IdxExpr->getSourceRange(); + return false; + } + + unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX); + if (IdxSource < 1 || (!Proto->isVariadic() && IdxSource > NumParams)) { + S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) + << &AI << AttrArgNum << IdxExpr->getSourceRange(); + return false; + } + + Idx = ParamIdx(IdxSource, D); + return true; +} + +static void handleNonNullFuncPtrParams(Sema &S, Decl *D, const ParsedAttr &AL, QualType Ty) { + const FunctionProtoType *Proto = nullptr; + if (Ty->isFunctionPointerType() || Ty->isBlockPointerType()) + Ty = Ty->getPointeeType(); + const FunctionType *FT = Ty->getAs(); + if (FT) + Proto = dyn_cast(FT); + if (Proto == nullptr) + return; + SmallVector NonNullArgs; + for (unsigned I = 0; I < AL.getNumArgs(); ++I) { + Expr *Ex = AL.getArgAsExpr(I); + ParamIdx Idx; + if (!checkFunctionTypeIndex(S, D, AL, I + 1, Ex, Idx, Proto)) + return; + + // Is the function type argument a pointer type + if (!attrNonNullArgCheck( + S, Proto->getParamType(Idx.getASTIndex()), AL, + Ex->getSourceRange(), + SourceRange())) + continue; + + NonNullArgs.push_back(Idx); + } + ParamIdx *Start = NonNullArgs.data(); + unsigned Size = NonNullArgs.size(); + llvm::array_pod_sort(Start, Start + Size); + D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, Start, Size)); +} + +static void handleNonNullAttrVarAndField(Sema &S, Decl *D, const ParsedAttr &AL) { + const auto *VD = dyn_cast(D); + if (VD == nullptr || + !attrNonNullArgCheck(S, VD->getType(), AL, SourceRange(), D->getSourceRange())) { + return; + } + if (VD->getType()->isFunctionPointerType() && AL.getNumArgs() > 0) + handleNonNullFuncPtrParams(S, D, AL, VD->getType()); + else + D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0)); +} + static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector NonNullArgs; for (unsigned I = 0; I < AL.getNumArgs(); ++I) { @@ -1598,6 +1669,22 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0)); } +static void handleReturnsNonNullFuncPtr(Sema &S, Decl *D, const ParsedAttr &AL) { + const auto *VD = dyn_cast(D); + if (VD == nullptr || !VD->getType()->isFunctionPointerType()) { + S.Diag(AL.getLoc(), diag::warn_attribute_function_pointer) << AL; + return; + } + QualType Ty = VD->getType()->getPointeeType(); + const FunctionType *FT = Ty->getAs(); + if (FT == nullptr) + return; + if (!attrNonNullArgCheck(S, FT->getReturnType(), AL, SourceRange(), D->getSourceRange(), true)) { + return; + } + D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL)); +} + static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType ResultType = getFunctionOrMethodResultType(D); SourceRange SR = getFunctionOrMethodResultSourceRange(D); @@ -7612,6 +7699,296 @@ EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr( *this, D, AL); } +//===----------------------------------------------------------------------===// +// EnhanceC Attribute +//===----------------------------------------------------------------------===// + +// If no indexs were specified to `count` attribute and only one pointer argument in function +// then the argument have the attribute; warn if there aren't any or more than one pointer argument. +// Skip this check if the attribute came from a macro expansion or a template instantiation. +static void checkPtrArgsInDefaultAttrIdx(SmallVector &Args, Sema &S, Decl *D, const ParsedAttr &AL) { + if (Args.empty() && AL.getLoc().isFileID() && !S.inTemplateInstantiation()) { + bool AnyPointers = isFunctionOrMethodVariadic(D); + unsigned PtrNum = 0; + for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); + I != E; ++I) { + QualType T = getFunctionOrMethodParamType(D, I); + if (T->isDependentType() || S.isValidPointerAttrType(T)) { + AnyPointers = true; + PtrNum++; + } + } + + if (!AnyPointers) + S.Diag(AL.getLoc(), diag::warn_attribute_no_pointers) << AL; + else if (AnyPointers && PtrNum > 1) + S.Diag(AL.getLoc(), diag::err_attribute_redundant_pointers) << AL; + } +} + +static SmallVector handleFuncPtrParams(Sema &S, Decl *D, const ParsedAttr &AL, QualType Ty) { + const FunctionProtoType *Proto = nullptr; + SmallVector Args; + if (Ty->isFunctionPointerType() || Ty->isBlockPointerType()) + Ty = Ty->getPointeeType(); + const FunctionType *FT = Ty->getAs(); + if (FT) + Proto = dyn_cast(FT); + if (Proto == nullptr) + return Args; + + for (unsigned I = 1; I < AL.getNumArgs(); ++I) { + Expr *Ex = AL.getArgAsExpr(I); + ParamIdx Idx; + if (!checkFunctionTypeIndex(S, D, AL, I + 1, Ex, Idx, Proto)) + continue; + + // Is the function type argument a pointer type + if (!attrNonNullArgCheck( + S, Proto->getParamType(Idx.getASTIndex()), AL, + Ex->getSourceRange(), + SourceRange())) + continue; + + Args.push_back(Idx); + } + return Args; +} + +// `count` attribute +static void handleCountFuncPtrParams(Sema &S, Decl *D, const ParsedAttr &AL, QualType Ty, Expr *LenExpr, bool isByte) { + SmallVector CountArgs = handleFuncPtrParams(S, D, AL, Ty); + unsigned Size = CountArgs.size(); + if (Size == 0) { + return; + } + ParamIdx *Start = CountArgs.data(); + llvm::array_pod_sort(Start, Start + Size); + if (isByte) + D->addAttr(::new (S.Context) ByteCountAttr(S.Context, AL, LenExpr, Start, Size)); + else + D->addAttr(::new (S.Context) CountAttr(S.Context, AL, LenExpr, Start, Size)); +} + +static void handleCountAttr(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + const auto *VD = dyn_cast(D); + if (VD != nullptr && + !attrNonNullArgCheck(S, VD->getType(), AL, SourceRange(), D->getSourceRange())) { + return; + } + // The first argument as `LenExpr` must exist + Expr *LenExpr = AL.getArgAsExpr(0); + if (VD->getType()->isFunctionPointerType() && AL.getNumArgs() > 1) { + handleCountFuncPtrParams(S, D, AL, VD->getType(), LenExpr, isByte); + } else { + if (isByte) + D->addAttr(::new (S.Context) ByteCountAttr(S.Context, AL, LenExpr)); + else + D->addAttr(::new (S.Context) CountAttr(S.Context, AL, LenExpr)); + } +} + +static void handleCountAttrFunc(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + SmallVector CountArgs; + // The first argument as `LenExpr` must exist + Expr *LenExpr = AL.getArgAsExpr(0); + for (unsigned I = 1; I < AL.getNumArgs(); ++I) { + Expr *Ex = AL.getArgAsExpr(I); + ParamIdx Idx; + if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx)) + return; + // Is the function argument a pointer type? + if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) && + !attrNonNullArgCheck( + S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL, + Ex->getSourceRange(), + getFunctionOrMethodParamRange(D, Idx.getASTIndex()))) + continue; + + CountArgs.push_back(Idx); + } + + checkPtrArgsInDefaultAttrIdx(CountArgs, S, D, AL); + ParamIdx *Start = CountArgs.data(); + unsigned Size = CountArgs.size(); + llvm::array_pod_sort(Start, Start + Size); + if (isByte) + D->addAttr(::new (S.Context) ByteCountAttr(S.Context, AL, LenExpr, Start, Size)); + else + D->addAttr(::new (S.Context) CountAttr(S.Context, AL, LenExpr, Start, Size)); + +} + +// `returns_count` attribute +static void handleReturnsCountAttr(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + QualType ResultType = getFunctionOrMethodResultType(D); + SourceRange SR = getFunctionOrMethodResultSourceRange(D); + if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR, + /* isReturnValue */ true)) + return; + Expr *LenExpr = AL.getArgAsExpr(0); + + if (isByte) + D->addAttr(::new (S.Context) ReturnsByteCountAttr(S.Context, AL, LenExpr)); + else + D->addAttr(::new (S.Context) ReturnsCountAttr(S.Context, AL, LenExpr)); +} + +static void handleReturnsCountFuncPtr(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + const auto *VD = dyn_cast(D); + if (VD == nullptr || !VD->getType()->isFunctionPointerType()) { + S.Diag(AL.getLoc(), diag::warn_attribute_function_pointer) << AL; + return; + } + QualType Ty = VD->getType()->getPointeeType(); + const FunctionType *FT = Ty->getAs(); + if (FT == nullptr) + return; + if (!attrNonNullArgCheck(S, FT->getReturnType(), AL, SourceRange(), D->getSourceRange(), true)) { + return; + } + Expr *LenExpr = AL.getArgAsExpr(0); + if (isByte) + D->addAttr(::new (S.Context) ReturnsByteCountAttr(S.Context, AL, LenExpr)); + else + D->addAttr(::new (S.Context) ReturnsCountAttr(S.Context, AL, LenExpr)); +} + +// `count_index` attribute +static void handleCountIndexFuncPtrParams(Sema &S, Decl *D, const ParsedAttr &AL, QualType Ty, const ParamIdx &LenIdx, bool isByte) { + SmallVector CountIndexArgs = handleFuncPtrParams(S, D, AL, Ty); + unsigned Size = CountIndexArgs.size(); + if (Size == 0) { + return; + } + ParamIdx *Start = CountIndexArgs.data(); + llvm::array_pod_sort(Start, Start + Size); + if (isByte) + D->addAttr(::new (S.Context) ByteCountIndexAttr(S.Context, AL, LenIdx, Start, Size)); + else + D->addAttr(::new (S.Context) CountIndexAttr(S.Context, AL, LenIdx, Start, Size)); +} + +static void handleCountIndexAttr(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + const auto *VD = dyn_cast(D); + if (VD != nullptr && + !attrNonNullArgCheck(S, VD->getType(), AL, SourceRange(), D->getSourceRange())) { + return; + } + + const Expr *LenVarIdxExpr = AL.getArgAsExpr(0); + int Idx; + // Parameter indices are 1-indexed, hence Index=1 + if (!checkPositiveIntArgument(S, AL, LenVarIdxExpr, Idx, /*Idx=*/1)) + return; + ParamIdx LenVarIdx(Idx, D); + + if (VD->getType()->isFunctionPointerType() && AL.getNumArgs() > 1) { + handleCountIndexFuncPtrParams(S, D, AL, VD->getType(), LenVarIdx, isByte); + } else { + if (dyn_cast(D) == nullptr) { + S.Diag(AL.getLoc(), diag::warn_attribute_function_pointer) << AL; + return; + } + if (isByte) + D->addAttr(::new (S.Context) ByteCountIndexAttr(S.Context, AL, LenVarIdx)); + else + D->addAttr(::new (S.Context) CountIndexAttr(S.Context, AL, LenVarIdx)); + } +} + +static void handleCountIndexAttrFunc(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + if (AL.getNumArgs() == 1) { + S.Diag(AL.getLoc(), diag::err_attribute_zero_pointer) << AL; + return; + } + // The first argument as `LenVarIndex` must be integer type + ParamIdx LenVarIdx; + const Expr *LenExpr = AL.getArgAsExpr(0); + if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, LenExpr, LenVarIdx)) + return; + const ParmVarDecl *Param = dyn_cast(D)->getParamDecl(LenVarIdx.getASTIndex()); + if (!Param->getType()->isIntegerType()) { + SourceLocation SrcLoc = LenExpr->getBeginLoc(); + S.Diag(SrcLoc, diag::err_attribute_integers_only) << AL << Param->getSourceRange(); + return; + } + + SmallVector CountIndexArgs; + for (unsigned I = 1; I < AL.getNumArgs(); ++I) { + Expr *Ex = AL.getArgAsExpr(I); + ParamIdx Idx; + if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx)) + return; + // Is the function argument a pointer type? + if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) && + !attrNonNullArgCheck( + S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL, + Ex->getSourceRange(), + getFunctionOrMethodParamRange(D, Idx.getASTIndex()))) + continue; + + CountIndexArgs.push_back(Idx); + } + + checkPtrArgsInDefaultAttrIdx(CountIndexArgs, S, D, AL); + unsigned Size = CountIndexArgs.size(); + ParamIdx *Start = CountIndexArgs.data(); + llvm::array_pod_sort(Start, Start + Size); + if (isByte) + D->addAttr(::new (S.Context) ByteCountIndexAttr(S.Context, AL, LenVarIdx, Start, Size)); + else + D->addAttr(::new (S.Context) CountIndexAttr(S.Context, AL, LenVarIdx, Start, Size)); +} + +// `returns_count_index` attribute +static void handleReturnsCountIndexAttr(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + QualType ResultType = getFunctionOrMethodResultType(D); + SourceRange SR = getFunctionOrMethodResultSourceRange(D); + if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR, + /* isReturnValue */ true)) + return; + const Expr *LenVarIdxExpr = AL.getArgAsExpr(0); + ParamIdx LenVarIdx; + if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, LenVarIdxExpr, LenVarIdx)) + return; + const ParmVarDecl *Param = dyn_cast(D)->getParamDecl(LenVarIdx.getASTIndex()); + if (!Param->getType()->isIntegerType()) { + SourceLocation SrcLoc = LenVarIdxExpr->getBeginLoc(); + S.Diag(SrcLoc, diag::err_attribute_integers_only) << AL << Param->getSourceRange(); + return; + } + if (isByte) + D->addAttr(::new (S.Context) ReturnsByteCountIndexAttr(S.Context, AL, LenVarIdx)); + else + D->addAttr(::new (S.Context) ReturnsCountIndexAttr(S.Context, AL, LenVarIdx)); +} + +static void handleReturnsCountIndexFuncPtr(Sema &S, Decl *D, const ParsedAttr &AL, bool isByte = false) { + const auto *VD = dyn_cast(D); + if (VD == nullptr || !VD->getType()->isFunctionPointerType()) { + S.Diag(AL.getLoc(), diag::warn_attribute_function_pointer) << AL; + return; + } + QualType Ty = VD->getType()->getPointeeType(); + const FunctionType *FT = Ty->getAs(); + if (FT == nullptr) + return; + if (!attrNonNullArgCheck(S, FT->getReturnType(), AL, SourceRange(), D->getSourceRange(), true)) { + return; + } + const Expr *LenVarIdxExpr = AL.getArgAsExpr(0); + int Idx; + // Parameter indices are 1-indexed, hence Index=1 + if (!checkPositiveIntArgument(S, AL, LenVarIdxExpr, Idx, /*Idx=*/1)) + return; + ParamIdx LenVarIdx(Idx, D); + if (isByte) + D->addAttr(::new (S.Context) ReturnsByteCountIndexAttr(S.Context, AL, LenVarIdx)); + else + D->addAttr(::new (S.Context) ReturnsCountIndexAttr(S.Context, AL, LenVarIdx)); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -7847,11 +8224,16 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_NonNull: if (auto *PVD = dyn_cast(D)) handleNonNullAttrParameter(S, PVD, AL); + else if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleNonNullAttrVarAndField(S, D, AL); else handleNonNullAttr(S, D, AL); break; case ParsedAttr::AT_ReturnsNonNull: - handleReturnsNonNullAttr(S, D, AL); + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleReturnsNonNullFuncPtr(S, D, AL); + else + handleReturnsNonNullAttr(S, D, AL); break; case ParsedAttr::AT_NoEscape: handleNoEscapeAttr(S, D, AL); @@ -8326,6 +8708,63 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_EnforceTCBLeaf: handleEnforceTCBAttr(S, D, AL); break; + + // EnhanceC attribute + case ParsedAttr::AT_Count: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleCountAttr(S, D, AL); + else + handleCountAttrFunc(S, D, AL); + break; + + case ParsedAttr::AT_ReturnsCount: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleReturnsCountFuncPtr(S, D, AL); + else + handleReturnsCountAttr(S, D, AL); + break; + + case ParsedAttr::AT_CountIndex: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleCountIndexAttr(S, D, AL); + else + handleCountIndexAttrFunc(S, D, AL); + break; + + case ParsedAttr::AT_ReturnsCountIndex: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleReturnsCountIndexFuncPtr(S, D, AL); + else + handleReturnsCountIndexAttr(S, D, AL); + break; + + case ParsedAttr::AT_ByteCount: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleCountAttr(S, D, AL, true); + else + handleCountAttrFunc(S, D, AL, true); + break; + + case ParsedAttr::AT_ReturnsByteCount: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleReturnsCountFuncPtr(S, D, AL, true); + else + handleReturnsCountAttr(S, D, AL, true); + break; + + case ParsedAttr::AT_ByteCountIndex: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleCountIndexAttr(S, D, AL, true); + else + handleCountIndexAttrFunc(S, D, AL, true); + break; + + case ParsedAttr::AT_ReturnsByteCountIndex: + if ((dyn_cast(D) != nullptr) || dyn_cast(D) != nullptr) + handleReturnsCountIndexFuncPtr(S, D, AL, true); + else + handleReturnsCountIndexAttr(S, D, AL, true); + break; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 45616dadcbee4a86e5b0c60b4a756c8ba4dfd1c7..ae8508d6c6018e3903e3fe305a1421ddd215e6fe 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -373,7 +373,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, } if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) { - if (const auto *VD = dyn_cast(D)) + if (auto *VD = dyn_cast(D)) checkDeviceDecl(VD, Loc); if (!Context.getTargetInfo().isTLSSupported()) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index af61c82c2002e806a9ee6b5d185d3b29cd2b36e4..c1c6a4bf5c6829b85946c172d71ea64d32a4f67b 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -432,15 +432,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, void Sema::handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, - Optional> Mangling) { + Optional> Mangling) { if (Mangling) { - unsigned ManglingNumber; bool HasKnownInternalLinkage; + unsigned ManglingNumber, DeviceManglingNumber; Decl *ManglingContextDecl; - std::tie(ManglingNumber, HasKnownInternalLinkage, ManglingContextDecl) = - Mangling.getValue(); + std::tie(HasKnownInternalLinkage, ManglingNumber, DeviceManglingNumber, + ManglingContextDecl) = Mangling.getValue(); Class->setLambdaMangling(ManglingNumber, ManglingContextDecl, HasKnownInternalLinkage); + Class->setDeviceLambdaManglingNumber(DeviceManglingNumber); return; } @@ -476,6 +477,7 @@ void Sema::handleLambdaNumbering( unsigned ManglingNumber = MCtx->getManglingNumber(Method); Class->setLambdaMangling(ManglingNumber, ManglingContextDecl, HasKnownInternalLinkage); + Class->setDeviceLambdaManglingNumber(MCtx->getDeviceManglingNumber(Method)); } } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 78707484f588c7a2fee01a4df001b50c7def9845..4063c185388d426dee7815e1ae354406373e83f3 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1884,8 +1884,7 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { static bool isOpenMPDeviceDelayedContext(Sema &S) { assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); - return !S.isInOpenMPTargetExecutionDirective() && - !S.isInOpenMPDeclareTargetContext(); + return !S.isInOpenMPTargetExecutionDirective(); } namespace { @@ -1898,11 +1897,11 @@ enum class FunctionEmissionStatus { } // anonymous namespace Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID) { + unsigned DiagID, + FunctionDecl *FD) { assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); - FunctionDecl *FD = getCurFunctionDecl(); SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; if (FD) { FunctionEmissionStatus FES = getEmissionStatus(FD); @@ -1911,6 +1910,13 @@ Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, Kind = SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::Unknown: + // TODO: We should always delay diagnostics here in case a target + // region is in a function we do not emit. However, as the + // current diagnostics are associated with the function containing + // the target region and we do not emit that one, we would miss out + // on diagnostics for the target region itself. We need to anchor + // the diagnostics with the new generated function *or* ensure we + // emit diagnostics associated with the surrounding function. Kind = isOpenMPDeviceDelayedContext(*this) ? SemaDiagnosticBuilder::K_Deferred : SemaDiagnosticBuilder::K_Immediate; @@ -1925,14 +1931,15 @@ Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, } } - return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this); } Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID) { + unsigned DiagID, + FunctionDecl *FD) { assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && "Expected OpenMP host compilation."); - FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl()); + FunctionEmissionStatus FES = getEmissionStatus(FD); SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; switch (FES) { case FunctionEmissionStatus::Emitted: @@ -1948,7 +1955,7 @@ Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, break; } - return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this); } static OpenMPDefaultmapClauseKind diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index b24a8ab110b25a1c647305eaeda7da95373f1ddc..f4308b3c9d4173bafb2d7e2f380a1a23fe14af58 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -402,7 +402,8 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { } StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, - ArrayRef Elts, bool isStmtExpr) { + ArrayRef Elts, bool isStmtExpr, + SafeScopeSpecifier SafeSpec, SourceLocation SafeLoc) { const unsigned NumElts = Elts.size(); // If we're in C89 mode, check that we don't have any decls after stmts. If @@ -433,7 +434,12 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); } - return CompoundStmt::Create(Context, Elts, L, R); + return CompoundStmt::Create(Context, Elts, L, R, SafeSpec, SafeLoc); +} + +void Sema::ActOnPragmaSafe(PragmaSafeStatus St) { + SafeScopeSpecifier spec = St == PSS_On ? SS_Safe : SS_Unsafe; + SetPragmaSafeInfo(spec); } ExprResult diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0a596e50658bda852667dac689000643ec212d67..3c68f9458e589328bd136c27d8b7cf58c0353c4d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -12504,10 +12504,11 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { E->getCaptureDefault()); getDerived().transformedLocalDecl(OldClass, {Class}); - Optional> Mangling; + Optional> Mangling; if (getDerived().ReplacingOriginal()) - Mangling = std::make_tuple(OldClass->getLambdaManglingNumber(), - OldClass->hasKnownLambdaInternalLinkage(), + Mangling = std::make_tuple(OldClass->hasKnownLambdaInternalLinkage(), + OldClass->getLambdaManglingNumber(), + OldClass->getDeviceLambdaManglingNumber(), OldClass->getLambdaContextDecl()); // Build the call operator. diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 6bfb9bd783b5a70bd4a305c85898ef8f7f69b769..cb827fc05f7da1f1f6f8305ffc095d56d856e830 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -865,6 +865,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // after everything else is read. FD->setStorageClass(static_cast(Record.readInt())); + FD->setSafeSpecifier(static_cast(Record.readInt())); FD->setInlineSpecified(Record.readInt()); FD->setImplicitlyInline(Record.readInt()); FD->setVirtualAsWritten(Record.readInt()); @@ -1748,6 +1749,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.NumExplicitCaptures = Record.readInt(); Lambda.HasKnownInternalLinkage = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); + D->setDeviceLambdaManglingNumber(Record.readInt()); Lambda.ContextDecl = readDeclID(); Lambda.Captures = (Capture *)Reader.getContext().Allocate( sizeof(Capture) * Lambda.NumCaptures); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 0e1af53303b421f178fc21a4de4e45c5e7278322..931cfbedffc507f12b72bb07e4584ee7dd9f1b90 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -153,6 +153,7 @@ void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) { VisitStmt(S); SmallVector Stmts; unsigned NumStmts = Record.readInt(); + S->setSafeSpecifier(static_cast(Record.readInt())); while (NumStmts--) Stmts.push_back(Record.readSubStmt()); S->setStmts(Stmts); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6bfa7b0e7d6dd442523a48d04852804b7fbe05e6..40900af6f9e00744b10d0c1fc350bc028bbc1ef5 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5667,6 +5667,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(Lambda.NumExplicitCaptures); Record->push_back(Lambda.HasKnownInternalLinkage); Record->push_back(Lambda.ManglingNumber); + Record->push_back(D->getDeviceLambdaManglingNumber()); AddDeclRef(D->getLambdaContextDecl()); AddTypeSourceInfo(Lambda.MethodTyInfo); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 2cb44bf9038b524b5635bbb49fcc2aa79a476664..3aeac4b53407d87c68263a2cac35cbd12ffd1ff0 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -545,6 +545,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { // FunctionDecl's body is handled last at ASTWriterDecl::Visit, // after everything else is written. Record.push_back(static_cast(D->getStorageClass())); // FIXME: stable encoding + Record.push_back(D->getSafeSpecifier()); Record.push_back(D->isInlineSpecified()); Record.push_back(D->isInlined()); Record.push_back(D->isVirtualAsWritten()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index d4f669ea0183c75de6682405ce02da1b8b1867d7..b3df5fe9739ed55bc6a1aa463b90bf5ac8a4c594 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -81,6 +81,7 @@ void ASTStmtWriter::VisitNullStmt(NullStmt *S) { void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) { VisitStmt(S); Record.push_back(S->size()); + Record.push_back(S->getSafeSpecifier()); for (auto *CS : S->body()) Record.AddStmt(CS); Record.AddSourceLocation(S->getLBracLoc()); diff --git a/clang/test/CodeCompletion/function-overloads.cpp b/clang/test/CodeCompletion/function-overloads.cpp index 11c864c281070099259bdb2f8147a87a327a0661..7b8ccef1d580fd07c12ff32292ba10cc9b65eff4 100644 --- a/clang/test/CodeCompletion/function-overloads.cpp +++ b/clang/test/CodeCompletion/function-overloads.cpp @@ -21,6 +21,8 @@ namespace NS { void test_adl() { NS::X x; g(x, x); + (void)(f)(1, 2, 3); + (void)(test, test, test, f)(1, 2, 3); } // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s @@ -31,6 +33,10 @@ void test_adl() { // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:7 %s -o - | \ // RUN: FileCheck -check-prefix=CHECK-CC5 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:24:13 %s -o - | \ +// RUN: FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:25:31 %s -o - | \ +// RUN: FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y) // CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>) // CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A( diff --git a/clang/test/CodeCompletion/member-access.c b/clang/test/CodeCompletion/member-access.c index 72afbf2ff947910cb6a04d2e04b293fcf46084a3..545349f71731bf45b95b39a8cc10597a9d9efce6 100644 --- a/clang/test/CodeCompletion/member-access.c +++ b/clang/test/CodeCompletion/member-access.c @@ -29,3 +29,10 @@ void test3(struct Point2 *p) { // RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:24:5 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: x (requires fix-it: {24:4-24:5} to "->") + +void test4(struct Point *p) { + (int)(p)->x; + (int)(0,1,2,3,4,p)->x; +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:34:13 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:35:23 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s diff --git a/clang/test/CodeGen/X86/avx512-reduceIntrin.c b/clang/test/CodeGen/X86/avx512-reduceIntrin.c index d8a1130f3cef0024743e03c77f8d3e872ae3bbef..62580ca1914e964f1bf2defac6b61f5efe778d3f 100644 --- a/clang/test/CodeGen/X86/avx512-reduceIntrin.c +++ b/clang/test/CodeGen/X86/avx512-reduceIntrin.c @@ -11,13 +11,13 @@ long long test_mm512_reduce_add_epi64(__m512i __W){ long long test_mm512_reduce_mul_epi64(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_mul_epi64( // CHECK: call i64 @llvm.vector.reduce.mul.v8i64(<8 x i64> %{{.*}}) - return _mm512_reduce_mul_epi64(__W); + return _mm512_reduce_mul_epi64(__W); } long long test_mm512_reduce_or_epi64(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_or_epi64( // CHECK: call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> %{{.*}}) - return _mm512_reduce_or_epi64(__W); + return _mm512_reduce_or_epi64(__W); } long long test_mm512_reduce_and_epi64(__m512i __W){ @@ -31,7 +31,7 @@ long long test_mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_add_epi64(__M, __W); + return _mm512_mask_reduce_add_epi64(__M, __W); } long long test_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W){ @@ -39,7 +39,7 @@ long long test_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.mul.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_mul_epi64(__M, __W); + return _mm512_mask_reduce_mul_epi64(__M, __W); } long long test_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W){ @@ -47,7 +47,7 @@ long long test_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.and.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_and_epi64(__M, __W); + return _mm512_mask_reduce_and_epi64(__M, __W); } long long test_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W){ @@ -55,30 +55,30 @@ long long test_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_or_epi64(__M, __W); + return _mm512_mask_reduce_or_epi64(__M, __W); } int test_mm512_reduce_add_epi32(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_add_epi32( // CHECK: call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_add_epi32(__W); + return _mm512_reduce_add_epi32(__W); } int test_mm512_reduce_mul_epi32(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_mul_epi32( // CHECK: call i32 @llvm.vector.reduce.mul.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_mul_epi32(__W); + return _mm512_reduce_mul_epi32(__W); } int test_mm512_reduce_or_epi32(__m512i __W){ // CHECK: call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_or_epi32(__W); + return _mm512_reduce_or_epi32(__W); } int test_mm512_reduce_and_epi32(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_and_epi32( // CHECK: call i32 @llvm.vector.reduce.and.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_and_epi32(__W); + return _mm512_reduce_and_epi32(__W); } int test_mm512_mask_reduce_add_epi32(__mmask16 __M, __m512i __W){ @@ -86,7 +86,7 @@ int test_mm512_mask_reduce_add_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_add_epi32(__M, __W); + return _mm512_mask_reduce_add_epi32(__M, __W); } int test_mm512_mask_reduce_mul_epi32(__mmask16 __M, __m512i __W){ @@ -94,7 +94,7 @@ int test_mm512_mask_reduce_mul_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.mul.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_mul_epi32(__M, __W); + return _mm512_mask_reduce_mul_epi32(__M, __W); } int test_mm512_mask_reduce_and_epi32(__mmask16 __M, __m512i __W){ @@ -102,7 +102,7 @@ int test_mm512_mask_reduce_and_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.and.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_and_epi32(__M, __W); + return _mm512_mask_reduce_and_epi32(__M, __W); } int test_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W){ @@ -110,61 +110,65 @@ int test_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_or_epi32(__M, __W); + return _mm512_mask_reduce_or_epi32(__M, __W); } -double test_mm512_reduce_add_pd(__m512d __W){ +double test_mm512_reduce_add_pd(__m512d __W, double ExtraAddOp){ // CHECK-LABEL: @test_mm512_reduce_add_pd( -// CHECK: call double @llvm.vector.reduce.fadd.v8f64(double 0.000000e+00, <8 x double> %{{.*}}) - return _mm512_reduce_add_pd(__W); +// CHECK-NOT: reassoc +// CHECK: call reassoc double @llvm.vector.reduce.fadd.v8f64(double -0.000000e+00, <8 x double> %{{.*}}) +// CHECK-NOT: reassoc + return _mm512_reduce_add_pd(__W) + ExtraAddOp; } -double test_mm512_reduce_mul_pd(__m512d __W){ +double test_mm512_reduce_mul_pd(__m512d __W, double ExtraMulOp){ // CHECK-LABEL: @test_mm512_reduce_mul_pd( -// CHECK: call double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) - return _mm512_reduce_mul_pd(__W); +// CHECK-NOT: reassoc +// CHECK: call reassoc double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) +// CHECK-NOT: reassoc + return _mm512_reduce_mul_pd(__W) * ExtraMulOp; } float test_mm512_reduce_add_ps(__m512 __W){ // CHECK-LABEL: @test_mm512_reduce_add_ps( -// CHECK: call float @llvm.vector.reduce.fadd.v16f32(float 0.000000e+00, <16 x float> %{{.*}}) - return _mm512_reduce_add_ps(__W); +// CHECK: call reassoc float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}}) + return _mm512_reduce_add_ps(__W); } float test_mm512_reduce_mul_ps(__m512 __W){ // CHECK-LABEL: @test_mm512_reduce_mul_ps( -// CHECK: call float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) - return _mm512_reduce_mul_ps(__W); +// CHECK: call reassoc float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) + return _mm512_reduce_mul_ps(__W); } double test_mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W){ // CHECK-LABEL: @test_mm512_mask_reduce_add_pd( // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} -// CHECK: call double @llvm.vector.reduce.fadd.v8f64(double 0.000000e+00, <8 x double> %{{.*}}) - return _mm512_mask_reduce_add_pd(__M, __W); +// CHECK: call reassoc double @llvm.vector.reduce.fadd.v8f64(double -0.000000e+00, <8 x double> %{{.*}}) + return _mm512_mask_reduce_add_pd(__M, __W); } double test_mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W){ // CHECK-LABEL: @test_mm512_mask_reduce_mul_pd( // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} -// CHECK: call double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) - return _mm512_mask_reduce_mul_pd(__M, __W); +// CHECK: call reassoc double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) + return _mm512_mask_reduce_mul_pd(__M, __W); } float test_mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W){ // CHECK-LABEL: @test_mm512_mask_reduce_add_ps( // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> {{.*}} -// CHECK: call float @llvm.vector.reduce.fadd.v16f32(float 0.000000e+00, <16 x float> %{{.*}}) - return _mm512_mask_reduce_add_ps(__M, __W); +// CHECK: call reassoc float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}}) + return _mm512_mask_reduce_add_ps(__M, __W); } float test_mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W){ // CHECK-LABEL: @test_mm512_mask_reduce_mul_ps( // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> %{{.*}} -// CHECK: call float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) - return _mm512_mask_reduce_mul_ps(__M, __W); +// CHECK: call reassoc float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) + return _mm512_mask_reduce_mul_ps(__M, __W); } diff --git a/clang/test/CodeGen/altivec.c b/clang/test/CodeGen/altivec.c index d69c34d821901b0f61ab66169397cf59fef179e7..86b570f15d0807f351b885719dd2fe5aa0ba7ae3 100644 --- a/clang/test/CodeGen/altivec.c +++ b/clang/test/CodeGen/altivec.c @@ -6,9 +6,6 @@ // RUN: %clang_cc1 -target-feature +altivec -mabi=vec-extabi -target-cpu pwr8 -triple powerpc64-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-BE // RUN: not %clang_cc1 -target-feature +altivec -mabi=vec-default -target-cpu pwr8 -triple powerpc-unknown-aix -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR // RUN: not %clang_cc1 -target-feature +altivec -mabi=vec-default -target-cpu pwr8 -triple powerpc64-unknown-aix -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR - -// RUN: not %clang -S -emit-llvm -maltivec -mcpu=pwr8 -target powerpc-unknown-aix %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR -// RUN: not %clang -S -emit-llvm -maltivec -mcpu=pwr8 -target powerpc64-unknown-aix %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR // RUN: %clang -S -emit-llvm -maltivec -mabi=vec-extabi -mcpu=pwr8 -target powerpc-unknown-aix %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-BE // RUN: %clang -S -emit-llvm -maltivec -mabi=vec-extabi -mcpu=pwr8 -target powerpc64-unknown-aix %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-BE // RUN: not %clang -S -emit-llvm -maltivec -mabi=vec-default -mcpu=pwr8 -triple powerpc-unknown-aix -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR diff --git a/clang/test/CodeGen/attr-mustprogress-0.c b/clang/test/CodeGen/attr-mustprogress-0.c deleted file mode 100644 index 2af24e88ceef7029a775b197f268c190b5de0588..0000000000000000000000000000000000000000 --- a/clang/test/CodeGen/attr-mustprogress-0.c +++ /dev/null @@ -1,184 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -std=c89 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s - -int a = 0; -int b = 0; - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f1() { - for (; 1;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f2() { - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @F( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F() { - for (; 1;) { - } - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @w1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void w1() { - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @w2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: ret void -// -void w2() { - while (a == b) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @W( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] -// CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] -// -void W() { - while (a == b) { - } - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @d1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d1() { - do { - } while (1); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @d2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d2() { - do { - } while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @D( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D() { - do { - } while (1); - do { - } while (a == b); -} diff --git a/clang/test/CodeGen/attr-mustprogress-0.cpp b/clang/test/CodeGen/attr-mustprogress-0.cpp deleted file mode 100644 index 3a180cc6b5ad545c4db06656af9b3a34cadf1e3c..0000000000000000000000000000000000000000 --- a/clang/test/CodeGen/attr-mustprogress-0.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s - -int a = 0; -int b = 0; - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2f1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f1() { - for (; 1;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2f2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f2() { - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Fv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F() { - for (; 1;) { - } - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2w1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void w1() { - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2w2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: ret void -// -void w2() { - while (a == b) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Wv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] -// CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] -// -void W() { - while (a == b) { - } - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2d1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d1() { - do { - } while (1); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2d2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d2() { - do { - } while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Dv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D() { - do { - } while (1); - do { - } while (a == b); -} diff --git a/clang/test/CodeGen/attr-mustprogress-1.c b/clang/test/CodeGen/attr-mustprogress.c similarity index 47% rename from clang/test/CodeGen/attr-mustprogress-1.c rename to clang/test/CodeGen/attr-mustprogress.c index 2ff068b8b90aa725165857b6e29da87fe044b000..1f83cd44b3083d0ae91ba3f7662072ea0d3f9e3d 100644 --- a/clang/test/CodeGen/attr-mustprogress-1.c +++ b/clang/test/CodeGen/attr-mustprogress.c @@ -1,31 +1,35 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s +// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s +// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s +// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s +// +// RUN: %clang_cc1 -std=c11 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s +// RUN: %clang_cc1 -std=c11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s int a = 0; int b = 0; -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK: datalayout +// +// CHECK-NOT: mustprogress // CHECK-LABEL: @f0( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NOT: br label [[FOR_COND]], !llvm.loop !{{.*}} +// CHECK-NOT: br {{.*}}!llvm.loop // void f0() { for (; ;) ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @f1( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 true, label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end: // CHECK-NEXT: ret void // @@ -34,17 +38,19 @@ void f1() { } } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @f2( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]] +// C99-NOT: br {{.*}} !llvm.loop +// C11: br label %for.cond, !llvm.loop [[LOOP1:!.*]] +// FINITE: br label %for.cond, !llvm.loop [[LOOP1:!.*]] // CHECK: for.end: // CHECK-NEXT: ret void // @@ -53,23 +59,25 @@ void f2() { } } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @F( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 true, label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] +// CHECK-NEXT: br label %for.cond1 // CHECK: for.cond1: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body2, label %for.end3 // CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]], [[LOOP4:!llvm.loop !.*]] +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// FINITE: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] // CHECK: for.end3: // CHECK-NEXT: ret void // @@ -80,29 +88,31 @@ void F() { } } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @w1( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] +// CHECK-NEXT: br label %while.body // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] +// CHECK-NOT: br {{.*}}, !llvm.loop // void w1() { while (1) { } } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @w2( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] +// CHECK-NEXT: br label %while.cond // CHECK: while.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP5:!llvm.loop !.*]] +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br label %while.cond, !llvm.loop [[LOOP3:!.*]] +// FINITE: br label %while.cond, !llvm.loop [[LOOP3:!.*]] // CHECK: while.end: // CHECK-NEXT: ret void // @@ -111,7 +121,7 @@ void w2() { } } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @W( // CHECK-NEXT: entry: // CHECK-NEXT: br label [[WHILE_COND:%.*]] @@ -119,13 +129,15 @@ void w2() { // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP6:!llvm.loop !.*]] +// C99-NOT: br {{.*}} !llvm.loop +// C11: br label %while.cond, !llvm.loop [[LOOP4:!.*]] +// FINITE: br label %while.cond, !llvm.loop [[LOOP4:!.*]] // CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] +// CHECK-NEXT: br label %while.body2 // CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] +// CHECK-NOT: br {{.*}} !llvm.loop // void W() { while (a == b) { @@ -134,14 +146,14 @@ void W() { } } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @d1( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end: // CHECK-NEXT: ret void // @@ -150,17 +162,19 @@ void d1() { } while (1); } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @d2( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP7:!llvm.loop !.*]] +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP5:!.*]] +// FINITE: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP5:!.*]] // CHECK: do.end: // CHECK-NEXT: ret void // @@ -169,23 +183,25 @@ void d2() { } while (a == b); } -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-NOT: mustprogress // CHECK-LABEL: @D( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] +// CHECK-NOT: br label {{.*}}, !llvm.loop // CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] +// CHECK-NEXT: br label %do.body1 // CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] +// CHECK-NEXT: br label %do.cond2 // CHECK: do.cond2: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], [[LOOP8:!llvm.loop !.*]] +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP6:!.*]] +// FINITE: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP6:!.*]] // CHECK: do.end3: // CHECK-NEXT: ret void // @@ -195,3 +211,11 @@ void D() { do { } while (a == b); } + +// C11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]} +// C11: [[MP]] = !{!"llvm.loop.mustprogress"} +// C11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]} +// C11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]} +// C11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]} +// C11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} +// C11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} diff --git a/clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c b/clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c index e07c680bb370246da486ae3db63278047dd07d49..b167b776e385e9ef7bf31dcc95f00831e16b1856 100644 --- a/clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c +++ b/clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c @@ -4,10 +4,11 @@ #define _(x, y) (__builtin_preserve_enum_value((x), (y))) enum AA { + VAL0 = 0, VAL1 = 2, VAL2 = 0xffffffff80000000UL, }; -typedef enum { VAL10 = -2, VAL11 = 0xffff8000, } __BB; +typedef enum { VAL00, VAL10 = -2, VAL11 = 0xffff8000, } __BB; unsigned unit1() { return _(*(enum AA *)VAL1, 0) + _(*(__BB *)VAL10, 1); @@ -17,10 +18,16 @@ unsigned unit2() { return _(*(enum AA *)VAL2, 0) + _(*(__BB *)VAL11, 1); } +unsigned unit3() { + return _(*(enum AA *)VAL0, 0) + _(*(__BB *)VAL00, 1); +} + // CHECK: @0 = private unnamed_addr constant [7 x i8] c"VAL1:2\00", align 1 // CHECK: @1 = private unnamed_addr constant [9 x i8] c"VAL10:-2\00", align 1 // CHECK: @2 = private unnamed_addr constant [17 x i8] c"VAL2:-2147483648\00", align 1 // CHECK: @3 = private unnamed_addr constant [17 x i8] c"VAL11:4294934528\00", align 1 +// CHECK: @4 = private unnamed_addr constant [7 x i8] c"VAL0:0\00", align 1 +// CHECK: @5 = private unnamed_addr constant [8 x i8] c"VAL00:0\00", align 1 // CHECK: call i64 @llvm.bpf.preserve.enum.value(i32 0, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @0, i32 0, i32 0), i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ENUM_AA:[0-9]+]] // CHECK: call i64 @llvm.bpf.preserve.enum.value(i32 1, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @1, i32 0, i32 0), i64 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_ENUM:[0-9]+]] @@ -28,5 +35,8 @@ unsigned unit2() { // CHECK: call i64 @llvm.bpf.preserve.enum.value(i32 2, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @2, i32 0, i32 0), i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ENUM_AA]] // CHECK: call i64 @llvm.bpf.preserve.enum.value(i32 3, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @3, i32 0, i32 0), i64 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_ENUM]] +// CHECK: call i64 @llvm.bpf.preserve.enum.value(i32 4, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @4, i32 0, i32 0), i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ENUM_AA]] +// CHECK: call i64 @llvm.bpf.preserve.enum.value(i32 5, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @5, i32 0, i32 0), i64 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_ENUM]] + // CHECK: ![[ENUM_AA]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "AA" // CHECK: ![[TYPEDEF_ENUM]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__BB" diff --git a/clang/test/CodeGen/builtins-ppc-fpconstrained.c b/clang/test/CodeGen/builtins-ppc-fpconstrained.c index 880c0c339ef334a89cfb5438b363c36e3ee639d4..909210996064cdb7f17b25abab3c7e2302fe754e 100644 --- a/clang/test/CodeGen/builtins-ppc-fpconstrained.c +++ b/clang/test/CodeGen/builtins-ppc-fpconstrained.c @@ -11,6 +11,9 @@ // RUN: -fallow-half-arguments-and-returns -S -ffp-exception-behavior=strict \ // RUN: -o - %s | FileCheck --check-prefix=CHECK-ASM \ // RUN: --check-prefix=FIXME-CHECK %s +// RUN: %clang_cc1 -triple powerpcspe -S -ffp-exception-behavior=strict \ +// RUN: -target-feature +spe -fexperimental-strict-floating-point -emit-llvm \ +// RUN: %s -o - | FileCheck --check-prefix=CHECK-CONSTRAINED %s typedef __attribute__((vector_size(4 * sizeof(float)))) float vec_float; typedef __attribute__((vector_size(2 * sizeof(double)))) double vec_double; diff --git a/clang/test/CodeGen/complex-builtins.c b/clang/test/CodeGen/complex-builtins.c index 96c0e71170167e594416f9e2471fc6953907746b..6fea8a9f028c941c38c0d9681d4ae5ce01a2073a 100644 --- a/clang/test/CodeGen/complex-builtins.c +++ b/clang/test/CodeGen/complex-builtins.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] __builtin_cpow(f,f); __builtin_cpowf(f,f); __builtin_cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/complex-libcalls.c b/clang/test/CodeGen/complex-libcalls.c index 9bd419a838217fe1ef2a1535f573679e927ff2e5..44d6849c0a71763dbc4cc4158ca092373df35121 100644 --- a/clang/test/CodeGen/complex-libcalls.c +++ b/clang/test/CodeGen/complex-libcalls.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] cpow(f,f); cpowf(f,f); cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/enable_if.c b/clang/test/CodeGen/enable_if.c index 14550b9e2db935cfa96d9e9824ec637705bec556..327a201cdeba16a0af05ff640ad7d2f706f0b5df 100644 --- a/clang/test/CodeGen/enable_if.c +++ b/clang/test/CodeGen/enable_if.c @@ -31,22 +31,22 @@ void bar(int m) __attribute__((overloadable, enable_if(m > 0, ""))); void bar(int m) __attribute__((overloadable, enable_if(1, ""))); // CHECK-LABEL: define{{.*}} void @test2 void test2() { - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi void (*p)(int) = bar; - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi void (*p2)(int) = &bar; - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi p = bar; - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi p = &bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) void *vp1 = (void*)&bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) void *vp2 = (void*)bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) vp1 = (void*)&bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) vp1 = (void*)bar; } @@ -54,13 +54,13 @@ void baz(int m) __attribute__((overloadable, enable_if(1, ""))); void baz(int m) __attribute__((overloadable)); // CHECK-LABEL: define{{.*}} void @test3 void test3() { - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi void (*p)(int) = baz; - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi void (*p2)(int) = &baz; - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi p = baz; - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi p = &baz; } @@ -71,13 +71,13 @@ void qux(int m) __attribute__((overloadable, enable_if(1, ""), void qux(int m) __attribute__((overloadable, enable_if(1, ""))); // CHECK-LABEL: define{{.*}} void @test4 void test4() { - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi void (*p)(int) = qux; - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi void (*p2)(int) = &qux; - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi p = qux; - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi p = &qux; } @@ -90,6 +90,6 @@ void test5() { int foo(char *i __attribute__((pass_object_size(0)))) __attribute__((enable_if(1, ""), overloadable)); - // CHECK: call i32 @_Z3fooUa9enable_ifIXLi1EEEPcU17pass_object_size0 + // CHECK: call i32 @_Z3fooUa9enable_ifILi1EEPcU17pass_object_size0 foo((void*)0); } diff --git a/clang/test/CodeGen/function-attributes.c b/clang/test/CodeGen/function-attributes.c index ffb86a6cd272c90a4c9fccff5a7d80585d2a7fd4..f14f24801006b7713bf422794a7d517ec032f096 100644 --- a/clang/test/CodeGen/function-attributes.c +++ b/clang/test/CodeGen/function-attributes.c @@ -115,5 +115,5 @@ void f20(void) { // CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} } // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } // CHECK: attributes [[NR]] = { noreturn optsize } -// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } +// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone willreturn } // CHECK: attributes [[RT_CALL]] = { optsize returns_twice } diff --git a/clang/test/CodeGen/ppc-xmmintrin.c b/clang/test/CodeGen/ppc-xmmintrin.c index e9466b32257f0650273e6a311a065768bba46441..32a5e5a7cdaf773d8fae428eda0be67cde736928 100644 --- a/clang/test/CodeGen/ppc-xmmintrin.c +++ b/clang/test/CodeGen/ppc-xmmintrin.c @@ -3,8 +3,12 @@ // RUN: %clang -S -emit-llvm -target powerpc64-unknown-linux-gnu -mcpu=pwr8 -ffreestanding -DNO_WARN_X86_INTRINSICS %s \ // RUN: -fno-discard-value-names -mllvm -disable-llvm-optzns -o - | llvm-cxxfilt -n | FileCheck %s --check-prefixes=CHECK,CHECK-BE +// RUN: %clang -x c++ -fsyntax-only -target powerpc64-unknown-linux-gnu -mcpu=pwr8 -ffreestanding -DNO_WARN_X86_INTRINSICS %s \ +// RUN: -fno-discard-value-names -mllvm -disable-llvm-optzns // RUN: %clang -S -emit-llvm -target powerpc64le-unknown-linux-gnu -mcpu=pwr8 -ffreestanding -DNO_WARN_X86_INTRINSICS %s \ // RUN: -fno-discard-value-names -mllvm -disable-llvm-optzns -o - | llvm-cxxfilt -n | FileCheck %s --check-prefixes=CHECK,CHECK-LE +// RUN: %clang -x c++ -fsyntax-only -target powerpc64le-unknown-linux-gnu -mcpu=pwr8 -ffreestanding -DNO_WARN_X86_INTRINSICS %s \ +// RUN: -fno-discard-value-names -mllvm -disable-llvm-optzns #include @@ -1426,7 +1430,7 @@ test_mul() { void __attribute__((noinline)) test_prefetch() { - _mm_prefetch(ms, i); + _mm_prefetch(ms, _MM_HINT_NTA); } // CHECK-LABEL: @test_prefetch diff --git a/clang/test/CodeGen/profile-filter.c b/clang/test/CodeGen/profile-filter.c index 5415ff96cb1450d88bcf6ee1d7b73f7f0b2776f3..dc5a31e872a1bf6bf6dbe6f75d4f862cb52eda6f 100644 --- a/clang/test/CodeGen/profile-filter.c +++ b/clang/test/CodeGen/profile-filter.c @@ -28,11 +28,11 @@ unsigned i; // EXCLUDE: noprofile // EXCLUDE: @test1 unsigned test1() { - // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // FUNC: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // SECTION-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // EXCLUDE-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 + // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // FUNC: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // SECTION-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // EXCLUDE-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) return i + 1; } @@ -47,10 +47,10 @@ unsigned test1() { // EXCLUDE-NOT: noprofile // EXCLUDE: @test2 unsigned test2() { - // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // FUNC-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // SECTION: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // EXCLUDE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 + // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // FUNC-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // SECTION: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // EXCLUDE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) return i - 1; } diff --git a/clang/test/CodeGen/pseudo-probe-emit.c b/clang/test/CodeGen/pseudo-probe-emit.c index 059673b6992e845a27771c7f0ad29c2be70007e5..fccc8f04844ddee491a1e58638cccfb7a2df1e17 100644 --- a/clang/test/CodeGen/pseudo-probe-emit.c +++ b/clang/test/CodeGen/pseudo-probe-emit.c @@ -6,12 +6,12 @@ void bar(); void go(); void foo(int x) { - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0, i64 -1) if (x == 0) - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0, i64 -1) bar(); else - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0, i64 -1) go(); - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0, i64 -1) } diff --git a/clang/test/CodeGenCUDA/unnamed-types.cu b/clang/test/CodeGenCUDA/unnamed-types.cu index 59bfa6d7a18f18044884c38e1d4504d04cafcfd9..f598117d969daeb6ba1ffb7ab7775331ef011654 100644 --- a/clang/test/CodeGenCUDA/unnamed-types.cu +++ b/clang/test/CodeGenCUDA/unnamed-types.cu @@ -1,12 +1,17 @@ // RUN: %clang_cc1 -std=c++11 -x hip -triple x86_64-linux-gnu -aux-triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s --check-prefix=HOST +// RUN: %clang_cc1 -std=c++11 -x hip -triple x86_64-pc-windows-msvc -aux-triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s --check-prefix=MSVC // RUN: %clang_cc1 -std=c++11 -x hip -triple amdgcn-amd-amdhsa -fcuda-is-device -emit-llvm %s -o - | FileCheck %s --check-prefix=DEVICE #include "Inputs/cuda.h" // HOST: @0 = private unnamed_addr constant [43 x i8] c"_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_\00", align 1 +// HOST: @1 = private unnamed_addr constant [60 x i8] c"_Z2k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_\00", align 1 +// Check that, on MSVC, the same device kernel mangling name is generated. +// MSVC: @0 = private unnamed_addr constant [43 x i8] c"_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_\00", align 1 +// MSVC: @1 = private unnamed_addr constant [60 x i8] c"_Z2k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_\00", align 1 __device__ float d0(float x) { - return [](float x) { return x + 2.f; }(x); + return [](float x) { return x + 1.f; }(x); } __device__ float d1(float x) { @@ -14,11 +19,21 @@ __device__ float d1(float x) { } // DEVICE: amdgpu_kernel void @_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_( +// DEVICE: define internal float @_ZZZ2f1PfENKUlS_E_clES_ENKUlfE_clEf( template __global__ void k0(float *p, F f) { p[0] = f(p[0]) + d0(p[1]) + d1(p[2]); } +// DEVICE: amdgpu_kernel void @_Z2k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_( +// DEVICE: define internal float @_ZZ2f1PfENKUlfE_clEf( +// DEVICE: define internal float @_ZZ2f1PfENKUlffE_clEff( +// DEVICE: define internal float @_ZZ2f1PfENKUlfE0_clEf( +template +__global__ void k1(float *p, F0 f0, F1 f1, F2 f2) { + p[0] = f0(p[0]) + f1(p[1], p[2]) + f2(p[3]); +} + void f0(float *p) { [](float *p) { *p = 1.f; @@ -29,11 +44,17 @@ void f0(float *p) { // linkages are still required to keep the original `internal` linkage. // HOST: define internal void @_ZZ2f1PfENKUlS_E_clES_( -// DEVICE: define internal float @_ZZZ2f1PfENKUlS_E_clES_ENKUlfE_clEf( void f1(float *p) { [](float *p) { - k0<<<1,1>>>(p, [] __device__ (float x) { return x + 1.f; }); + k0<<<1,1>>>(p, [] __device__ (float x) { return x + 3.f; }); }(p); + k1<<<1,1>>>(p, + [] __device__ (float x) { return x + 4.f; }, + [] __device__ (float x, float y) { return x * y; }, + [] __device__ (float x) { return x + 5.f; }); } // HOST: @__hip_register_globals // HOST: __hipRegisterFunction{{.*}}@_Z17__device_stub__k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_{{.*}}@0 +// HOST: __hipRegisterFunction{{.*}}@_Z17__device_stub__k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_{{.*}}@1 +// MSVC: __hipRegisterFunction{{.*}}@"??$k0@V@?0???R1?0??f1@@YAXPEAM@Z@QEBA@0@Z@@@YAXPEAMV@?0???R0?0??f1@@YAX0@Z@QEBA@0@Z@@Z{{.*}}@0 +// MSVC: __hipRegisterFunction{{.*}}@"??$k1@V@?0??f1@@YAXPEAM@Z@V@?0??2@YAX0@Z@V@?0??2@YAX0@Z@@@YAXPEAMV@?0??f1@@YAX0@Z@V@?0??1@YAX0@Z@V@?0??1@YAX0@Z@@Z{{.*}}@1 diff --git a/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp b/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp index 25400a552e5d20d1c6289e34ecfe5236341111b2..e1d539608fcc8499a43683402c65c46b98f647f2 100644 --- a/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp +++ b/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp @@ -15,8 +15,8 @@ int f(void) { // CHECK: declare i32 @_Z1tv() [[TF2:#[0-9]+]] // CHECK: attributes [[TF]] = { {{.*}} } -// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[NUW_RN]] = { nounwind readnone willreturn{{.*}} } +// CHECK: attributes [[NUW_RO]] = { nounwind readonly willreturn{{.*}} } // CHECK: attributes [[TF2]] = { {{.*}} } -// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone willreturn } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/CodeGen/attr-mustprogress-1.cpp b/clang/test/CodeGenCXX/attr-mustprogress.cpp similarity index 43% rename from clang/test/CodeGen/attr-mustprogress-1.cpp rename to clang/test/CodeGenCXX/attr-mustprogress.cpp index 945d74663c6d1ee41f4c4c868faec85d9043eb21..48ac7ad938ba3d1196b43c2a422ba45b620c70cf 100644 --- a/clang/test/CodeGen/attr-mustprogress-1.cpp +++ b/clang/test/CodeGenCXX/attr-mustprogress.cpp @@ -1,30 +1,42 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s +// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s +// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s +// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s + +// Make sure -ffinite-loops overrides -std=c++98 for loops. +// RUN: %clang_cc1 -std=c++98 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s + +// Make sure -fno-finite-loops overrides -std=c++11 +// RUN: %clang_cc1 -std=c++11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s int a = 0; int b = 0; -// CHECK: Function Attrs: noinline nounwind optnone +// CHECK: datalayout + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2f0v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NOT: br label [[FOR_COND]], !llvm.loop !{{.*}} +// CHECK-NOT: br {{.*}} llvm.loop void f0() { for (; ;) ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2f1v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 true, label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end: // CHECK-NEXT: ret void // @@ -33,17 +45,21 @@ void f1() { ; } -// CHECK: Function Attrs: noinline nounwind optnone mustprogress +// CXX98-NOT: mustprogress +// CXX11: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2f2v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11: br label %for.cond, !llvm.loop [[LOOP1:!.*]] +// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP1:!.*]] // CHECK: for.end: // CHECK-NEXT: ret void // @@ -52,23 +68,27 @@ void f2() { ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z1Fv( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 true, label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] +// CHECK-NEXT: br label %for.cond1 // CHECK: for.cond1: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body2, label %for.end3 // CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]], [[LOOP4:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// FINITE-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] // CHECK: for.end3: // CHECK-NEXT: ret void // @@ -79,23 +99,27 @@ void F() { ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2F2v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label %for.cond // CHECK: for.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end // CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]], [[LOOP5:!llvm.loop !.*]] +// CXX98_NOT: br {{.*}} !llvm.loop +// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]] +// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]] // CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] +// CHECK-NEXT: br label %for.cond1 // CHECK: for.cond1: -// CHECK-NEXT: br i1 true, label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] +// CHECK-NEXT: br i1 true, label %for.body2, label %for.end3 // CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end3: // CHECK-NEXT: ret void // @@ -106,29 +130,35 @@ void F2() { ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2w1v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] +// CHECK-NEXT: br label %while.body // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] +// CHECK-NOT: br {{.*}}, !llvm.loop // void w1() { while (1) ; } -// CHECK: Function Attrs: noinline nounwind optnone mustprogress +// CXX98-NOT: mustprogress +// CXX11: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2w2v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] +// CHECK-NEXT: br label %while.cond // CHECK: while.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP6:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]] +// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]] // CHECK: while.end: // CHECK-NEXT: ret void // @@ -137,21 +167,25 @@ void w2() { ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z1Wv( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] +// CHECK-NEXT: br label %while.cond // CHECK: while.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP7:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]] +// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]] // CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] +// CHECK-NEXT: br label %while.body2 // CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] +// CHECK-NOT: br {{.*}}, !llvm.loop // void W() { while (a == b) @@ -160,12 +194,14 @@ void W() { ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2W2v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] +// CHECK-NEXT: br label %while.body // CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] +// CHECK-NOT: br {{.*}}, !llvm.loop // void W2() { while (1) @@ -174,14 +210,16 @@ void W2() { ; } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2d1v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end: // CHECK-NEXT: ret void // @@ -191,17 +229,21 @@ void d1() { while (1); } -// CHECK: Function Attrs: noinline nounwind optnone mustprogress +// CXX98-NOT: mustprogress +// CXX11: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2d2v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP8:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]] +// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]] // CHECK: do.end: // CHECK-NEXT: ret void // @@ -211,23 +253,27 @@ void d2() { while (a == b); } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z1Dv( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] +// CHECK-NEXT: br label %do.body1 // CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] +// CHECK-NEXT: br label %do.cond2 // CHECK: do.cond2: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], [[LOOP9:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]] +// FINITE-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]] // CHECK: do.end3: // CHECK-NEXT: ret void // @@ -240,23 +286,27 @@ void D() { while (a == b); } -// CHECK: Function Attrs: noinline nounwind optnone +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2D2v( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] +// CHECK-NEXT: br label %do.body // CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] +// CHECK-NEXT: br label %do.cond // CHECK: do.cond: // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP10:!llvm.loop !.*]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]] +// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]] // CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] +// CHECK-NEXT: br label %do.body1 // CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] +// CHECK-NEXT: br label %do.cond2 // CHECK: do.cond2: -// CHECK-NEXT: br i1 true, label [[DO_BODY1]], label [[DO_END3:%.*]] +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end3: // CHECK-NEXT: ret void // @@ -269,3 +319,12 @@ void D2() { while (1); } +// CXX11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]} +// CXX11: [[MP]] = !{!"llvm.loop.mustprogress"} +// CXX11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]} +// CXX11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]} +// CXX11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]} +// CXX11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} +// CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} +// CXX11: [[LOOP7]] = distinct !{[[LOOP7]], [[MP]]} +// CXX11: [[LOOP8]] = distinct !{[[LOOP8]], [[MP]]} diff --git a/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp b/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp index 967c83496ab988744f18e8929fa50e4e9a3952fd..d30fefe55b4f6028138178b30fe5b4ce2f6a24b7 100644 --- a/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp +++ b/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp @@ -4,6 +4,7 @@ // RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s // RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s // RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s +// RUN: FileCheck -check-prefix=CHECK-DTOR -input-file=%t.ll %s using size_t = decltype(sizeof(int)); @@ -131,3 +132,94 @@ void test_ref_to_static_var() { // CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, i32** %r, int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant; } + +int not_constexpr; + +// __builtin_is_constant_evaluated() should never evaluate to true during +// destruction if it would not have done so during construction. +// +// FIXME: The standard doesn't say that it should ever return true when +// evaluating a destructor call, even for a constexpr variable. That seems +// obviously wrong. +struct DestructorBCE { + int n; + constexpr DestructorBCE(int n) : n(n) {} + constexpr ~DestructorBCE() { + if (!__builtin_is_constant_evaluated()) + not_constexpr = 1; + } +}; + +// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_1 +DestructorBCE global_dtor_bce_1(101); + +// CHECK-DTOR: load i32, i32* @not_constexpr +// CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} @global_dtor_bce_2, i32 +// CHECK-DTOR: atexit{{.*}} @_ZN13DestructorBCED{{.*}} @global_dtor_bce_2 +// CHECK-DTOR: } +DestructorBCE global_dtor_bce_2(not_constexpr); + +// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_3 +constexpr DestructorBCE global_dtor_bce_3(103); + +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_1v( +void test_dtor_bce_1() { + // Variable is neither constant initialized (because it has automatic storage + // duration) nor usable in constant expressions, so BCE should not return + // true during destruction. It would be OK if we replaced the constructor + // call with a direct store, but we should emit the destructor call. + + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}}, i32 201) + DestructorBCE local(201); + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_2v( +void test_dtor_bce_2() { + // Non-constant init => BCE is false in destructor. + + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} + DestructorBCE local(not_constexpr); + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_3v( +void test_dtor_bce_3() { + // Should never call dtor for a constexpr variable. + + // CHECK-DTOR-NOT: call {{.*}} @_ZN13DestructorBCEC1Ei( + constexpr DestructorBCE local(203); + // CHECK-DTOR-NOT: @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_1v( +void test_dtor_bce_static_1() { + // Variable is constant initialized, so BCE returns true during constant + // destruction. + + // CHECK: store i32 301 + // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}} + static DestructorBCE local(301); + // CHECK-DTOR-NOT: @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_2v( +void test_dtor_bce_static_2() { + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} + static DestructorBCE local(not_constexpr); + // CHECK-DTOR: call {{.*}}atexit{{.*}} @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_3v( +void test_dtor_bce_static_3() { + // CHECK: store i32 303 + // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}} + static constexpr DestructorBCE local(303); + // CHECK-DTOR-NOT: @_ZN13DestructorBCED + // CHECK-DTOR: } +} diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index 46e7ed812cbc67508a99209059159b5f4221952e..80311aa320fe5884ccc1de0933cffc4d2f81477a 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -1,12 +1,23 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s -// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s -// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17 %s +// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - -Wno-c++11-extensions \ +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.8 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.9 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=4.0 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=5 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE12-CXX20 %s +// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - -Wno-c++11-extensions \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20 %s typedef __attribute__((vector_size(8))) long long v1xi64; void clang39(v1xi64) {} @@ -55,3 +66,73 @@ template void clang12_b(); // CHECK: @_Z9clang12_cIXadL_Z3arrEEEvv template void clang12_c() {} template void clang12_c<&arr>(); + + +/// Tests for changes in clang12: +namespace expr_primary { +struct A { + template struct Int {}; + template struct Ref {}; +}; + +/// Check various DeclRefExpr manglings + +// PRE12: @_ZN12expr_primary5test1INS_1AEEEvNT_3IntIXLi1EEEE +// V12: @_ZN12expr_primary5test1INS_1AEEEvNT_3IntILi1EEE +template void test1(typename T::template Int<1> a) {} +template void test1(typename A::template Int<1> a); + +enum Enum { EnumVal = 4 }; +int Global; + +// PRE12: @_ZN12expr_primary5test2INS_1AEEEvNT_3IntIXLNS_4EnumE4EEEE +// V12: @_ZN12expr_primary5test2INS_1AEEEvNT_3IntILNS_4EnumE4EEE +template void test2(typename T::template Int a) {} +template void test2(typename A::template Int<4> a); + +// CHECK: @_ZN12expr_primary5test3ILi3EEEvNS_1A3IntIXT_EEE +template void test3(typename A::template Int a) {} +template void test3<3>(A::Int<3> a); + +#if __cplusplus >= 202002L +// CHECK-CXX20: @_ZN12expr_primary5test4INS_1AEEEvNT_3RefIL_ZNS_6GlobalEEEE +template void test4(typename T::template Ref<(Global)> a) {} +template void test4(typename A::template Ref a); + +struct B { + struct X { + constexpr X(double) {} + constexpr X(int&) {} + }; + template struct Y {}; +}; + +// PRE12-CXX20: _ZN12expr_primary5test5INS_1BEEEvNT_1YIXLd3ff0000000000000EEEE +// V12-CXX20: _ZN12expr_primary5test5INS_1BEEEvNT_1YILd3ff0000000000000EEE +template void test5(typename T::template Y<1.0>) { } +template void test5(typename B::Y<1.0>); + +// PRE12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIL_ZZNS_5test6EiE1bEEEi +// V12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIXfp_EEEi +template auto test6(int b) -> typename T::template Y { return {}; } +template auto test6(int b) -> B::Y; +#endif + +/// Verify non-dependent type-traits within a dependent template arg. + +// PRE12: @_ZN12expr_primary5test7INS_1AEEEvNT_3IntIXLm1EEEE +// V12: @_ZN12expr_primary5test7INS_1AEEEvNT_3IntILm1EEE +template void test7(typename T::template Int a) {} +template void test7(A::Int<1>); + +// PRE12: @_ZN12expr_primary5test8ILi2EEEvu11matrix_typeIXLi1EEXT_EiE +// V12: @_ZN12expr_primary5test8ILi2EEEvu11matrix_typeILi1EXT_EiE +template using matrix1xN = int __attribute__((matrix_type(1, N))); +template void test8(matrix1xN a) {} +template void test8<2>(matrix1xN<2> a); + +// PRE12: @_ZN12expr_primary5test9EUa9enable_ifIXLi1EEEv +// V12: @_ZN12expr_primary5test9EUa9enable_ifILi1EEv +void test9(void) __attribute__((enable_if(1, ""))) {} + +} diff --git a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp index 27ac682c10f52d141adb113b2e90d5da0d27119f..409b62da62c129cb2e1f26cb61c488c94319e0f7 100644 --- a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp +++ b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp @@ -25,6 +25,6 @@ void test() { // CHECK: ![[C]] = !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-SAME: flags: DIFlagFwdDecl // CHECK-NOT: identifier - // CHECK: ![[MTYPE]] = !DISubroutineType(types: !{{.*}}) + // CHECK: ![[MTYPE]] = !DISubroutineType({{.*}}types: !{{.*}}) c.m(); } diff --git a/clang/test/CodeGenCXX/enable_if.cpp b/clang/test/CodeGenCXX/enable_if.cpp index 4e7707aaeed9c73a746e0e296e76911ce45f52d1..70386b87fcee36c38edbb747fb5cbcfdddee3183 100644 --- a/clang/test/CodeGenCXX/enable_if.cpp +++ b/clang/test/CodeGenCXX/enable_if.cpp @@ -5,7 +5,7 @@ int test5(int); template T test5(T) __attribute__((enable_if(1, "better than non-template"))); -// CHECK: @_Z5test5IiEUa9enable_ifIXLi1EEET_S0_ +// CHECK: @_Z5test5IiEUa9enable_ifILi1EET_S0_ int (*Ptr)(int) = &test5; // Test itanium mangling for attribute enable_if diff --git a/clang/test/CodeGenCXX/mangle-abi-tag.cpp b/clang/test/CodeGenCXX/mangle-abi-tag.cpp index 5d84096d24cd8eb47d3e591bdaf1ecb4ddbeb308..9e26604a2c448aaf553ba85bea70db4e402f219a 100644 --- a/clang/test/CodeGenCXX/mangle-abi-tag.cpp +++ b/clang/test/CodeGenCXX/mangle-abi-tag.cpp @@ -225,7 +225,7 @@ namespace pr30440 { template void g(F); template auto h(A ...a)->decltype (g (0, g < a > (a) ...)) { } -// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIL_ZZNS_1hEDpT_E1aEEfp_EEES2_( +// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIXfp_EEfp_EEEDpT_( void pr30440_test () { h(); diff --git a/clang/test/CodeGenCXX/mangle-alignof.cpp b/clang/test/CodeGenCXX/mangle-alignof.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a65c7e87a2d365a6469e69f4b2be0a6d7c27b32 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-alignof.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++11 -Wno-gnu-alignof-expression -emit-llvm %s -o - -triple=%itanium_abi_triple | FileCheck %s --check-prefix=CHECK-NEW +// RUN: %clang_cc1 -std=c++11 -Wno-gnu-alignof-expression -emit-llvm %s -o - -triple=%itanium_abi_triple -fclang-abi-compat=11 | FileCheck %s --check-prefix=CHECK-OLD + +// Verify the difference in mangling for alignof and __alignof__ in a new ABI +// compat mode. + +template void f1(decltype(alignof(T))) {} +template void f1(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f1IiEvDTatT_E +// CHECK-NEW: void @_Z2f1IiEvDTatT_E + +template void f2(decltype(__alignof__(T))) {} +template void f2(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f2IiEvDTatT_E +// CHECK-NEW: void @_Z2f2IiEvDTu11__alignof__T_E + +template void f3(decltype(alignof(T(0)))) {} +template void f3(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f3IiEvDTazcvT_Li0EE +// CHECK-NEW: void @_Z2f3IiEvDTazcvT_Li0EE + +template void f4(decltype(__alignof__(T(0)))) {} +template void f4(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f4IiEvDTazcvT_Li0EE +// CHECK-NEW: void @_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE diff --git a/clang/test/CodeGenCXX/mangle-concept.cpp b/clang/test/CodeGenCXX/mangle-concept.cpp index b0fcd586727e88adcdd7e172b489906b1aa73603..e60e6348a5f6d4b767c1cf079e94edb1639c363e 100644 --- a/clang/test/CodeGenCXX/mangle-concept.cpp +++ b/clang/test/CodeGenCXX/mangle-concept.cpp @@ -6,11 +6,11 @@ template struct S {}; template concept C = true; template S> f0() { return S>{}; } template S> f0<>(); -// CHECK: @_ZN5test12f0IiEENS_1SIXL_ZNS_1CIT_EEEEEEv( +// CHECK: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv( } template struct S {}; template concept C = true; template S> f0() { return S>{}; } template S> f0<>(); -// CHECK: @_Z2f0IiE1SIXL_Z1CIT_EEEEv( +// CHECK: @_Z2f0IiE1SIL_Z1CIT_EEEv( diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp index 40688de7e12e8ef592049f0752f6ae3eef387d8b..9b80a6d646955e35fa90aaaef6832b1e18c08c98 100644 --- a/clang/test/CodeGenCXX/mangle-template.cpp +++ b/clang/test/CodeGenCXX/mangle-template.cpp @@ -270,7 +270,7 @@ namespace test17 { // Note: there is no J...E here, because we can't form a pack argument, and // the 5u and 6u are mangled with the original type 'j' (unsigned int) not // with the resolved type 'i' (signed int). - // CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_EXLj5EEXT_EXLj6EEEE + // CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_ELj5EXT_ELj6EEE template void h(X) {} void i() { h<4, 1, 2, 3>({}); } @@ -323,7 +323,7 @@ namespace partially_dependent_template_args { // callee is unresolved, the rest mangle the converted argument Lj0E // because the callee is resolved. void h() { - // CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fIXLi0EEEcvT__EEE + // CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fILi0EEcvT__EEE g1({}); // CHECK: @_ZN33partially_dependent_template_args5test22g2IiEEvDTplclL_ZNS0_1fILj0EEEiNS0_1XEEilEEcvT__EE g2({}); diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index f8ea9960a5c505f673e27ff44ba168ed3b4e645b..6cec33e3758e718106a5a0b7a49c0d5eeecc2fdd 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1123,7 +1123,7 @@ namespace test56 { namespace test57 { struct X { template int f(); } x; template void f(decltype(x.f<0>() + N)) {} - // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fIXLi0EEEET_E + // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E template void f<0>(int); } diff --git a/clang/test/CodeGenCXX/matrix-type.cpp b/clang/test/CodeGenCXX/matrix-type.cpp index 9bde12e13b86adedcfdbb7404e6e1ccdda29d3e8..9e715e10ce1c6f7e7d09241db8031dcee8519649 100644 --- a/clang/test/CodeGenCXX/matrix-type.cpp +++ b/clang/test/CodeGenCXX/matrix-type.cpp @@ -215,14 +215,14 @@ void test_template_deduction() { // CHECK-NEXT: %m4 = alloca [144 x float], align 4 // CHECK-NEXT: %v = alloca %struct.selector.3, align 1 // CHECK-NEXT: %undef.agg.tmp4 = alloca %struct.selector.3, align 1 - // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeIXLm10EEXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m0) + // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m0) // CHECK-NEXT: call void @_Z10use_matrixIiE8selectorILi2EERu11matrix_typeILm10ELm10ET_E([100 x i32]* nonnull align 4 dereferenceable(400) %m1) - // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_EXLm10EET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m2) + // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m2) // CHECK-NEXT: call void @_Z10use_matrixIiLm12ELm12EE8selectorILi0EERu11matrix_typeIXT0_EXT1_ET_E([144 x i32]* nonnull align 4 dereferenceable(576) %m3) // CHECK-NEXT: call void @_Z10use_matrixILm12ELm12EE8selectorILi4EERu11matrix_typeIXT_EXT0_EfE([144 x float]* nonnull align 4 dereferenceable(576) %m4) // CHECK-NEXT: ret void - // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeIXLm10EEXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) + // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) // CHECK-NEXT: entry: // CHECK-NEXT: %m.addr = alloca [120 x i32]*, align 8 // CHECK-NEXT: store [120 x i32]* %m, [120 x i32]** %m.addr, align 8 @@ -236,7 +236,7 @@ void test_template_deduction() { // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable - // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_EXLm10EET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) + // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) // CHECK-NEXT: entry: // CHECK-NEXT: %m.addr = alloca [120 x i32]*, align 8 // CHECK-NEXT: store [120 x i32]* %m, [120 x i32]** %m.addr, align 8 @@ -277,10 +277,10 @@ void test_auto_t() { // CHECK-LABEL: define{{.*}} void @_Z11test_auto_tv() // CHECK-NEXT: entry: // CHECK-NEXT: %m = alloca [130 x i32], align 4 - // CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_EXLm10EEiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) + // CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) // CHECK-NEXT: ret void - // CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_EXLm10EEiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) + // CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) // CHECK-NEXT: entry: // CHECK-NEXT: %m.addr = alloca [130 x i32]*, align 8 // CHECK-NEXT: store [130 x i32]* %m, [130 x i32]** %m.addr, align 8 @@ -326,7 +326,7 @@ void test_use_matrix_2() { // CHECK-NEXT: store <40 x float> %call, <40 x float>* %0, align 4 // CHECK-NEXT: call void @_Z12use_matrix_2ILm2ELm12EE8selectorILi0EERu11matrix_typeIXplT_Li2EEXdvT0_Li2EEiERu11matrix_typeIXT_EXT0_EfE([24 x i32]* nonnull align 4 dereferenceable(96) %m1, [24 x float]* nonnull align 4 dereferenceable(96) %m2) // CHECK-NEXT: call void @_Z12use_matrix_2ILm5ELm8EE8selectorILi1EERu11matrix_typeIXplT_T0_EXT0_EiERu11matrix_typeIXT_EXmiT0_T_EfE([104 x i32]* nonnull align 4 dereferenceable(416) %m3, [15 x float]* nonnull align 4 dereferenceable(60) %m4) - // CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_EXLm10EEiE([50 x i32]* nonnull align 4 dereferenceable(200) %m5) + // CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE([50 x i32]* nonnull align 4 dereferenceable(200) %m5) // CHECK-NEXT: %1 = bitcast [20 x float]* %r4 to <20 x float>* // CHECK-NEXT: store <20 x float> %call2, <20 x float>* %1, align 4 // CHECK-NEXT: call void @_Z12use_matrix_3ILm6EE8selectorILi2EERu11matrix_typeIXmiT_Li2EEXT_EiE([24 x i32]* nonnull align 4 dereferenceable(96) %m1) @@ -357,7 +357,7 @@ void test_use_matrix_2() { // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable - // CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_EXLm10EEiE([50 x i32]* nonnull align 4 dereferenceable(200) %m1) + // CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE([50 x i32]* nonnull align 4 dereferenceable(200) %m1) // CHECK-NEXT: entry: // CHECK-NEXT: %m1.addr = alloca [50 x i32]*, align 8 // CHECK-NEXT: store [50 x i32]* %m1, [50 x i32]** %m1.addr, align 8 diff --git a/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp b/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp index ec26be292acccec71d8ba59f373950b43aa59239..5c02b1eb014c6d4b296bd531bc55c97f8d22eaeb 100644 --- a/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp +++ b/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s --check-prefixes=CHECK,CHECK-V12 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions -fclang-abi-compat=11 | FileCheck %s --check-prefixes=CHECK,CHECK-V11 // rdar://17784718 typedef struct _GUID @@ -24,11 +25,16 @@ struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) TestStruct struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) OtherStruct {}; -template void test_uuidofType(void *arg[sizeof(__uuidof(T))] = 0) {} +template void test_uuidofType(decltype(__uuidof(T)) arg) {} -template void test_uuidofExpr(void *arg[sizeof(__uuidof(typename T::member))] = 0) {} +template void test_uuidofExpr(decltype(__uuidof(T::member)) arg) {} -struct HasMember { typedef TestStruct member; }; +struct HasMember { + TestStruct member; +}; + +// Ensure that mangling an "expr-primary" argument is handled properly. +template void test_uuidofExpr2(decltype(T{}, __uuidof(HasMember::member)) arg) {} template struct UUIDTestTwo { UUIDTestTwo(); }; @@ -39,19 +45,27 @@ int main(int argc, const char * argv[]) // type had better not mention TestStruct or OtherStruct! UUIDTestTwo<__uuidof(TestStruct)> uuidof_test2; UUIDTestTwo<__uuidof(OtherStruct)> uuidof_test3; - test_uuidofType(); - test_uuidofExpr(); + test_uuidofType(GUID{}); + test_uuidofExpr(GUID{}); + test_uuidofExpr2(GUID{}); return 0; } // CHECK: define{{.*}} i32 @main -// CHECK: call void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: call void @_Z15test_uuidofTypeI10TestStructEvPPv(i8** null) -// CHECK: call void @_Z15test_uuidofExprI9HasMemberEvPPv(i8** null) - +// CHECK: call void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev( +// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev( +// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev( +// CHECK-V11: call void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E( +// CHECK-V12: call void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE( +// CHECK-V11: call void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofzsrT_6memberE( +// CHECK-V12: call void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE( +// CHECK-V11: call void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofzL_ZN9HasMember6memberEEE( +// CHECK-V12: call void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofL_ZN9HasMember6memberEEEE( // CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvPPv -// CHECK: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvPPv +// CHECK-V11: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E( +// CHECK-V12: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE( +// CHECK-V11: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofzsrT_6memberE( +// CHECK-V12: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE( +// CHECK-V11: define linkonce_odr void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofzL_ZN9HasMember6memberEEE( +// CHECK-V12: define linkonce_odr void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofL_ZN9HasMember6memberEEEE( // CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC2Ev diff --git a/clang/test/CodeGenCXX/trivial_abi.cpp b/clang/test/CodeGenCXX/trivial_abi.cpp index ac41f5cac08663d22e6bf33ef13b80980a9542fa..a4222c100311b17c8eb30e0f4aa8ca437a7d2610 100644 --- a/clang/test/CodeGenCXX/trivial_abi.cpp +++ b/clang/test/CodeGenCXX/trivial_abi.cpp @@ -262,3 +262,21 @@ void calleeExceptionLarge(Large, Large); void testExceptionLarge() { calleeExceptionLarge(Large(), Large()); } + +// PR42961 + +// CHECK: define{{.*}} @"_ZN3$_08__invokeEv"() +// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: %[[CALL:.*]] = call{{.*}} @"_ZNK3$_0clEv" +// CHECK: %[[COERCEDIVE:.*]] = getelementptr{{.*}} %[[COERCE]] +// CHECK: %[[COERCEVALIP:.*]] = inttoptr{{.*}} %[[CALL]] +// CHECK: %[[RETVALP:.*]] = bitcast %[[STRUCT_SMALL]]* %[[RETVAL]] +// CHECK: %[[COERCEP:.*]] = bitcast %[[STRUCT_SMALL]]* %[[COERCE]] +// CHECK: call {{.*}}memcpy{{.*}} %[[RETVALP]]{{.*}} %[[COERCEP]] +// CHECK: %[[COERCEDIVE1:.*]] = getelementptr{{.*}} %[[RETVAL]] +// CHECK: %[[TMP:.*]] = load{{.*}} %[[COERCEDIVE1]] +// CHECK: %[[COERCEVALPI:.*]] = ptrtoint{{.*}} %[[TMP]] +// CHECK: ret{{.*}} %[[COERCEVALPI]] + +Small (*fp)() = []() -> Small { return Small(); }; diff --git a/clang/test/CodeGenOpenCL/sampler.cl b/clang/test/CodeGenOpenCL/sampler.cl index e6bda49f51c8dd01fba7996b00f3bf912b82fefa..5ad8d0dbbf376b7a2a20829b812f28d51046be4b 100644 --- a/clang/test/CodeGenOpenCL/sampler.cl +++ b/clang/test/CodeGenOpenCL/sampler.cl @@ -39,7 +39,7 @@ kernel void foo(sampler_t smp_par) { // Case 2b sampler_t smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST; // CHECK: [[smp_ptr:%[A-Za-z0-9_\.]+]] = alloca %opencl.sampler_t addrspace(2)* - // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19) + // CHECK: [[SAMP:%[0-9]+]] = call spir_func %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19) // CHECK: store %opencl.sampler_t addrspace(2)* [[SAMP]], %opencl.sampler_t addrspace(2)** [[smp_ptr]] // Case 1b @@ -56,12 +56,12 @@ kernel void foo(sampler_t smp_par) { // Case 1a/2a fnc4smp(glb_smp); - // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) + // CHECK: [[SAMP:%[0-9]+]] = call spir_func %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // Case 1a/2c fnc4smp(glb_smp_const); - // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) + // CHECK: [[SAMP:%[0-9]+]] = call spir_func %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // Case 1c @@ -70,12 +70,12 @@ kernel void foo(sampler_t smp_par) { // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) fnc4smp(5); - // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 5) + // CHECK: [[SAMP:%[0-9]+]] = call spir_func %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 5) // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) const sampler_t const_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; fnc4smp(const_smp); - // CHECK: [[CONST_SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) + // CHECK: [[CONST_SAMP:%[0-9]+]] = call spir_func %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) // CHECK: store %opencl.sampler_t addrspace(2)* [[CONST_SAMP]], %opencl.sampler_t addrspace(2)** [[CONST_SMP_PTR:%[a-zA-Z0-9]+]] fnc4smp(const_smp); // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[CONST_SMP_PTR]] @@ -83,7 +83,7 @@ kernel void foo(sampler_t smp_par) { constant sampler_t constant_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; fnc4smp(constant_smp); - // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) + // CHECK: [[SAMP:%[0-9]+]] = call spir_func %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // TODO: enable sampler initialization with non-constant integer. diff --git a/clang/test/Driver/Xlinker-args.c b/clang/test/Driver/Xlinker-args.c index a44957cd8aef11311351cc218d736ffa21b0100b..cb045a1d40ac172e3c7bf1de039d31c170d79812 100644 --- a/clang/test/Driver/Xlinker-args.c +++ b/clang/test/Driver/Xlinker-args.c @@ -17,7 +17,7 @@ // LINUX: "--no-demangle" "-e" "_start" "one" "two" "three" "four" "-z" "five" "-r" {{.*}} "-T" "a.lds" // Check that we forward '-Xlinker' and '-Wl,' on Windows. -// RUN: %clang -target i686-pc-win32 -### \ +// RUN: %clang -target i686-pc-win32 -fuse-ld=link -### \ // RUN: -Xlinker one -Wl,two %s 2>&1 | \ // RUN: FileCheck -check-prefix=WIN %s // WIN: link.exe diff --git a/clang/test/Driver/cl-inputs.c b/clang/test/Driver/cl-inputs.c index 59455a0aa5e5c7e06a4f1bb673c9ce6fd43d6f09..8eb44517ee167a8bfcc087c3121fea1744a3912c 100644 --- a/clang/test/Driver/cl-inputs.c +++ b/clang/test/Driver/cl-inputs.c @@ -50,16 +50,16 @@ // RUN: %clang_cl -### /Tc - 2>&1 | FileCheck -check-prefix=STDINTc %s // STDINTc: "-x" "c" -// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -### -- %s cl-test.lib 2>&1 | FileCheck -check-prefix=LIBINPUT %s +// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -fuse-ld=link -### -- %s cl-test.lib 2>&1 | FileCheck -check-prefix=LIBINPUT %s // LIBINPUT: link.exe" // LIBINPUT: "cl-test.lib" -// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -### -- %s cl-test2.lib 2>&1 | FileCheck -check-prefix=LIBINPUT2 %s +// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -fuse-ld=link -### -- %s cl-test2.lib 2>&1 | FileCheck -check-prefix=LIBINPUT2 %s // LIBINPUT2: error: no such file or directory: 'cl-test2.lib' // LIBINPUT2: link.exe" // LIBINPUT2-NOT: "cl-test2.lib" -// RUN: %clang_cl -### -- %s /nonexisting.lib 2>&1 | FileCheck -check-prefix=LIBINPUT3 %s +// RUN: %clang_cl -fuse-ld=link -### -- %s /nonexisting.lib 2>&1 | FileCheck -check-prefix=LIBINPUT3 %s // LIBINPUT3: error: no such file or directory: '/nonexisting.lib' // LIBINPUT3: link.exe" // LIBINPUT3-NOT: "/nonexisting.lib" diff --git a/clang/test/Driver/cl-link-at-file.c b/clang/test/Driver/cl-link-at-file.c index 50ae07fadf5bf0beb11c4eff09b5d6fc2fd65e7c..4e665f89b74e1d0e5d3ffeac8f73fbaf8f533f53 100644 --- a/clang/test/Driver/cl-link-at-file.c +++ b/clang/test/Driver/cl-link-at-file.c @@ -7,7 +7,7 @@ // RUN: echo /link bar.lib baz.lib > %t.args // RUN: touch %t.obj -// RUN: %clang_cl -### @%t.args -- %t.obj 2>&1 | FileCheck %s -check-prefix=ARGS +// RUN: %clang_cl -fuse-ld=link -### @%t.args -- %t.obj 2>&1 | FileCheck %s -check-prefix=ARGS // If the "/link" option captures all remaining args beyond its response file, // it will also capture "--" and our input argument. In this case, Clang will // be clueless and will emit "argument unused" warnings. If PR17239 is properly diff --git a/clang/test/Driver/cl-link.c b/clang/test/Driver/cl-link.c index 142725fed8eb2ee1b0265460495a4eb3fd632224..e2f5397e913393bd10fafbfba9b66c518b732be9 100644 --- a/clang/test/Driver/cl-link.c +++ b/clang/test/Driver/cl-link.c @@ -2,14 +2,14 @@ // be interpreted as a command-line option, e.g. on Mac where %s is commonly // under /Users. -// RUN: %clang_cl /Tc%s -### /link foo bar baz 2>&1 | FileCheck --check-prefix=LINK %s -// RUN: %clang_cl /Tc%s -### /linkfoo bar baz 2>&1 | FileCheck --check-prefix=LINK %s +// RUN: %clang_cl /Tc%s -fuse-ld=link -### /link foo bar baz 2>&1 | FileCheck --check-prefix=LINK %s +// RUN: %clang_cl /Tc%s -fuse-ld=link -### /linkfoo bar baz 2>&1 | FileCheck --check-prefix=LINK %s // LINK: link.exe // LINK: "foo" // LINK: "bar" // LINK: "baz" -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN %s // ASAN: link.exe // ASAN: "-debug" // ASAN: "-incremental:no" @@ -19,7 +19,7 @@ // ASAN: "-wholearchive:{{.*}}clang_rt.asan_cxx-i386.lib" // ASAN: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /MD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /MD /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s // ASAN-MD: link.exe // ASAN-MD: "-debug" // ASAN-MD: "-incremental:no" @@ -29,13 +29,13 @@ // ASAN-MD: "-wholearchive:{{.*}}clang_rt.asan_dynamic_runtime_thunk-i386.lib" // ASAN-MD: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl /LD -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s -// RUN: %clang_cl /LDd -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s +// RUN: %clang_cl /LD -fuse-ld=link -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s +// RUN: %clang_cl /LDd -fuse-ld=link -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s // DLL: link.exe // "-dll" -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LDd /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LD /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LDd /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s // ASAN-DLL: link.exe // ASAN-DLL: "-dll" // ASAN-DLL: "-debug" @@ -43,13 +43,13 @@ // ASAN-DLL: "{{.*}}clang_rt.asan_dll_thunk-i386.lib" // ASAN-DLL: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl /Zi /Tc%s -### 2>&1 | FileCheck --check-prefix=DEBUG %s +// RUN: %clang_cl /Zi /Tc%s -fuse-ld=link -### 2>&1 | FileCheck --check-prefix=DEBUG %s // DEBUG: link.exe // DEBUG: "-debug" // PR27234 -// RUN: %clang_cl /Tc%s nonexistent.obj -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s -// RUN: %clang_cl /Tc%s nonexistent.lib -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.obj -fuse-ld=link -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.lib -fuse-ld=link -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s // NONEXISTENT-NOT: no such file // NONEXISTENT: link.exe // NONEXISTENT: "/libpath:somepath" diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 0b788ffcb852fd593371649c78699be0e23d465b..24d3c78643f85ea1d19ab16e1a72697813301789 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1089,20 +1089,6 @@ // CHECK-ANDROID-HASH-STYLE-M: "{{.*}}ld{{(.exe)?}}" // CHECK-ANDROID-HASH-STYLE-M: "--hash-style=gnu" -// Check that we pass --no-rosegment for pre-29 Android versions and do not for -// 29+. -// RUN: %clang %s -### -o %t.o 2>&1 \ -// RUN: --target=armv7-linux-android28 \ -// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ROSEGMENT-28 %s -// CHECK-ANDROID-ROSEGMENT-28: "{{.*}}ld{{(.exe)?}}" -// CHECK-ANDROID-ROSEGMENT-28: "--no-rosegment" -// -// RUN: %clang %s -### -o %t.o 2>&1 \ -// RUN: --target=armv7-linux-android29 \ -// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ROSEGMENT-29 %s -// CHECK-ANDROID-ROSEGMENT-29: "{{.*}}ld{{(.exe)?}}" -// CHECK-ANDROID-ROSEGMENT-29-NOT: "--no-rosegment" - // RUN: %clang %s -### -o %t.o 2>&1 \ // RUN: --target=armv7-linux-android21 \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-NOEXECSTACK %s diff --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c index 13dccd21bfd8d1c0ed7ec61c28670fe189d2f3ad..1ee17fc63c321359edade2c847b2c04282bb00d7 100644 --- a/clang/test/Driver/msvc-link.c +++ b/clang/test/Driver/msvc-link.c @@ -1,4 +1,4 @@ -// RUN: %clang -target i686-pc-windows-msvc -### %s 2>&1 | FileCheck --check-prefix=BASIC %s +// RUN: %clang -target i686-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=BASIC %s // BASIC: link.exe" // BASIC: "-out:a.exe" // BASIC: "-defaultlib:libcmt" @@ -6,7 +6,7 @@ // BASIC: "-nologo" // BASIC-NOT: "-Brepro" -// RUN: %clang -target i686-pc-windows-msvc -shared -o a.dll -### %s 2>&1 | FileCheck --check-prefix=DLL %s +// RUN: %clang -target i686-pc-windows-msvc -shared -o a.dll -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=DLL %s // DLL: link.exe" // DLL: "-out:a.dll" // DLL: "-defaultlib:libcmt" @@ -19,13 +19,13 @@ // LIBPATH: "-libpath:/usr/lib" // LIBPATH: "-nologo" -// RUN: %clang_cl /Brepro -### -- %s 2>&1 | FileCheck --check-prefix=REPRO %s +// RUN: %clang_cl /Brepro -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=REPRO %s // REPRO: link.exe" // REPRO: "-out:msvc-link.exe" // REPRO: "-nologo" // REPRO: "-Brepro" -// RUN: %clang_cl /Brepro- -### -- %s 2>&1 | FileCheck --check-prefix=NOREPRO %s +// RUN: %clang_cl /Brepro- -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=NOREPRO %s // NOREPRO: link.exe" // NOREPRO: "-out:msvc-link.exe" // NOREPRO: "-nologo" diff --git a/clang/test/Driver/openbsd.cpp b/clang/test/Driver/openbsd.cpp index 9293148680c8ca6614eeacc2762aeb1a13d4e0ff..23c365d28e7ed27c373b68d74b91d24d54aa38e4 100644 --- a/clang/test/Driver/openbsd.cpp +++ b/clang/test/Driver/openbsd.cpp @@ -6,7 +6,7 @@ // RUN: | FileCheck --check-prefix=CHECK-CXX %s // RUN: %clangxx %s -### -o %t.o -target arm-unknown-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CXX %s -// CHECK-CXX: "-lc++" "-lc++abi" "-lm" +// CHECK-CXX: "-lc++" "-lc++abi" "-lpthread" "-lm" // RUN: %clangxx %s -### -pg -o %t.o -target amd64-pc-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s @@ -16,4 +16,4 @@ // RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s // RUN: %clangxx %s -### -pg -o %t.o -target arm-unknown-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s -// CHECK-PG-CXX: "-lc++_p" "-lc++abi_p" "-lm_p" +// CHECK-PG-CXX: "-lc++_p" "-lc++abi_p" "-lpthread_p" "-lm_p" diff --git a/clang/test/Driver/ppc-f128-support-check.c b/clang/test/Driver/ppc-f128-support-check.c index 2e4b7a7ae09ce1e5b84fd1d7a57a0e85f627d209..24748905612ff47cd7ea31fdbc80f17df08a351a 100644 --- a/clang/test/Driver/ppc-f128-support-check.c +++ b/clang/test/Driver/ppc-f128-support-check.c @@ -1,7 +1,7 @@ // RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ -// RUN: -mcpu=pwr9 %s 2>&1 | FileCheck %s --check-prefix=HASF128 +// RUN: -mcpu=pwr9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 // RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ -// RUN: -mcpu=power9 %s 2>&1 | FileCheck %s --check-prefix=HASF128 +// RUN: -mcpu=power9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 // RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ // RUN: -mcpu=pwr8 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 diff --git a/clang/test/Driver/pseudo-probe-lto.c b/clang/test/Driver/pseudo-probe-lto.c new file mode 100644 index 0000000000000000000000000000000000000000..e319b8c0098bf409b50fefc6f57f0de9b14dda86 --- /dev/null +++ b/clang/test/Driver/pseudo-probe-lto.c @@ -0,0 +1,10 @@ +// RUN: touch %t.o +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fpseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=PROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto=thin -fpseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=PROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fno-pseudo-probe-for-profiling -fpseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=PROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto 2>&1 | FileCheck %s --check-prefix=NOPROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fno-pseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=NOPROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fpseudo-probe-for-profiling -fno-pseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=NOPROBE + +// PROBE: -plugin-opt=pseudo-probe-for-profiling +// NOPROBE-NOT: -plugin-opt=pseudo-probe-for-profiling diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c index 3762a4aef1b347f018a19ceaf266bf7309607d5e..cf148ca885d0953c25a8c8600cc04c073e484847 100644 --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -384,7 +384,7 @@ // RV32-EXPERIMENTAL-V-BADVERS: error: invalid arch name 'rv32iv0p1' // RV32-EXPERIMENTAL-V-BADVERS: unsupported version number 0.1 for experimental extension -// RUN: %clang -target riscv32-unknown-elf -march=rv32iv1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-V-GOODVERS %s // RV32-EXPERIMENTAL-V-GOODVERS: "-target-feature" "+experimental-v" @@ -412,7 +412,7 @@ // RV32-EXPERIMENTAL-ZVAMO-BADVERS: error: invalid arch name 'rv32izvamo0p1' // RV32-EXPERIMENTAL-ZVAMO-BADVERS: unsupported version number 0.1 for experimental extension -// RUN: %clang -target riscv32-unknown-elf -march=rv32izvamo1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: %clang -target riscv32-unknown-elf -march=rv32izvamo0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVAMO-GOODVERS %s // RV32-EXPERIMENTAL-ZVAMO-GOODVERS: "-target-feature" "+experimental-zvamo" @@ -431,6 +431,6 @@ // RV32-EXPERIMENTAL-ZVLSSEG-BADVERS: error: invalid arch name 'rv32izvlsseg0p1' // RV32-EXPERIMENTAL-ZVLSSEG-BADVERS: unsupported version number 0.1 for experimental extension -// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG-GOODVERS %s // RV32-EXPERIMENTAL-ZVLSSEG-GOODVERS: "-target-feature" "+experimental-zvlsseg" diff --git a/clang/test/Frontend/fixed_point_unary.c b/clang/test/Frontend/fixed_point_unary.c index 6ce760daba115d868f7441f18f6f0e083f88c207..849e38a94bc4822edc06f0d4fc87b8afce89c60a 100644 --- a/clang/test/Frontend/fixed_point_unary.c +++ b/clang/test/Frontend/fixed_point_unary.c @@ -90,7 +90,7 @@ void inc_usa() { // SIGNED-LABEL: @inc_uf( // SIGNED-NEXT: entry: // SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2 -// SIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], poison +// SIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], undef // SIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2 // SIGNED-NEXT: ret void // @@ -271,7 +271,7 @@ void dec_usa() { // SIGNED-LABEL: @dec_uf( // SIGNED-NEXT: entry: // SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2 -// SIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], poison +// SIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], undef // SIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2 // SIGNED-NEXT: ret void // diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp index f57faed4ed908fbf4eb0ba1406c5a70c4d4a04ac..2f46f354ee83fa2355563c6b050cf76d415be55a 100644 --- a/clang/test/Lexer/cxx-features.cpp +++ b/clang/test/Lexer/cxx-features.cpp @@ -181,7 +181,8 @@ #error "wrong value for __cpp_structured_bindings" #endif -#if check(nontype_template_args, 0, 0, 0, 201411, 201911, 201911) +#if check(nontype_template_args, 0, 0, 0, 201411, 201411, 201411) +// FIXME: 201911 in C++20 #error "wrong value for __cpp_nontype_template_args" #endif diff --git a/clang/test/OpenMP/critical_codegen.cpp b/clang/test/OpenMP/critical_codegen.cpp index 46fad63b3bd88db2c1773bfd83db5829d8dec1cd..d84f2b2af22bbe85e5bbf2b014b2f36f650bfa30 100644 --- a/clang/test/OpenMP/critical_codegen.cpp +++ b/clang/test/OpenMP/critical_codegen.cpp @@ -68,6 +68,31 @@ int main() { return a; } +// ALL-LABEL: lambda_critical +// TERM_DEBUG-LABEL: lambda_critical +void lambda_critical(int a, int b) { + auto l = [=]() { +#pragma omp critical + { + // ALL: call void @__kmpc_critical( + int c = a + b; + } + }; + + l(); + + auto l1 = [=]() { +#pragma omp parallel +#pragma omp critical + { + // ALL: call void @__kmpc_critical( + int c = a + b; + } + }; + + l1(); +} + struct S { int a; }; diff --git a/clang/test/OpenMP/linking.c b/clang/test/OpenMP/linking.c index 802553c1be7525de7aeb8c5253a125a7f9e85f1d..1c44396264705bb6638ed289cd83849b07f6bb01 100644 --- a/clang/test/OpenMP/linking.c +++ b/clang/test/OpenMP/linking.c @@ -81,7 +81,7 @@ // CHECK-LD-OVERRIDE-64: "-lgomp" "-lrt" // CHECK-LD-OVERRIDE-64: "-lpthread" "-lc" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: %clang -no-canonical-prefixes -fuse-ld=link %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=libomp -target x86_64-msvc-win32 -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-MSVC-LINK-64 %s // CHECK-MSVC-LINK-64: link.exe @@ -95,7 +95,7 @@ // SIMD-ONLY11-NOT: libomp // SIMD-ONLY11-NOT: libgomp // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: %clang -no-canonical-prefixes %s -fuse-ld=link -### -o %t.o 2>&1 \ // RUN: -fopenmp=libiomp5 -target x86_64-msvc-win32 -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-MSVC-ILINK-64 %s diff --git a/clang/test/OpenMP/master_codegen.cpp b/clang/test/OpenMP/master_codegen.cpp index 8554ad8e7deca941ece74a83da2bdbbce2c7b392..353284ea85411bc15dbf48bb809e0bfc86427fff 100644 --- a/clang/test/OpenMP/master_codegen.cpp +++ b/clang/test/OpenMP/master_codegen.cpp @@ -55,6 +55,41 @@ int main() { return a; } +// ALL-LABEL: lambda_master +// TERM_DEBUG-LABEL: lambda_master +void lambda_master(int a, int b) { + auto l = [=]() { +#pragma omp master + { + // ALL: call i32 @__kmpc_master( + int c = a + b; + } + }; + + l(); + + auto l1 = [=]() { +#pragma omp parallel +#pragma omp master + { + // ALL: call i32 @__kmpc_master( + int c = a + b; + } + }; + + l1(); + + auto l2 = [=]() { +#pragma omp parallel master + { + // ALL: call i32 @__kmpc_master( + int c = a + b; + } + }; + + l2(); +} + // ALL-LABEL: parallel_master // TERM_DEBUG-LABEL: parallel_master void parallel_master() { diff --git a/clang/test/OpenMP/nvptx_allocate_messages.cpp b/clang/test/OpenMP/nvptx_allocate_messages.cpp index a4d78b6ab58880d382e33e1942973401d75b7bbe..9a61da73eb390c8d4e533b0079b7ca2fe821a6bc 100644 --- a/clang/test/OpenMP/nvptx_allocate_messages.cpp +++ b/clang/test/OpenMP/nvptx_allocate_messages.cpp @@ -81,8 +81,7 @@ int main () { #endif // DEVICE && !REQUIRES #pragma omp allocate(b) #if defined(DEVICE) && !defined(REQUIRES) -// expected-note@+3 {{in instantiation of function template specialization 'foo' requested here}} -// expected-note@+2 {{called by 'main'}} +// expected-note@+2 2{{called by 'main'}} #endif // DEVICE && !REQUIRES return (foo() + bar()); } diff --git a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp index c71615d2521fc9ba59ae06d4db2936c677f2bb73..87ea00a90822eeddb49fe41110e202c9dfb894ef 100644 --- a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp +++ b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp @@ -52,6 +52,7 @@ int maini1() { #pragma omp target map(tofrom \ : a, b) { + // expected-note@+1 {{called by 'maini1'}} S s(a); static long aaa = 23; a = foo() + bar() + b + c + d + aa + aaa + FA(); // expected-note{{called by 'maini1'}} diff --git a/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp b/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp index 814a4756c01b400382a770e9d053e7cf5600fb04..a319c78f73c5673fb9641927b0fa11e7dccdc1bf 100644 --- a/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp +++ b/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp @@ -39,10 +39,12 @@ struct T1 { }; #ifndef _ARCH_PPC -// expected-note@+1 {{'boo' defined here}} +// expected-error@+2 {{'boo' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-note@+1 2{{'boo' defined here}} void boo(__float128 A) { return; } #else -// expected-note@+1 {{'boo' defined here}} +// expected-error@+2 {{'boo' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-note@+1 2{{'boo' defined here}} void boo(long double A) { return; } #endif #pragma omp declare target @@ -51,10 +53,11 @@ T f = a; void foo(T a = T()) { a = a + f; // expected-note {{called by 'foo'}} #ifndef _ARCH_PPC -// expected-error@+4 {{'boo' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-error@+5 {{'boo' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} #else -// expected-error@+2 {{'boo' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-error@+3 {{'boo' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} #endif +// expected-note@+1 {{called by 'foo'}} boo(0); return; } @@ -77,21 +80,147 @@ T1 bar1() { void baz1() { T1 t = bar1(); } + +inline void dead_inline_declare_target() { + long double *a, b = 0; + a = &b; +} +static void dead_static_declare_target() { + long double *a, b = 0; + a = &b; +} +template +void dead_template_declare_target() { + long double *a, b = 0; + a = &b; +} + +// expected-note@+2 {{'ld_return1a' defined here}} +// expected-error@+1 {{'ld_return1a' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +long double ld_return1a() { return 0; } +// expected-note@+2 {{'ld_arg1a' defined here}} +// expected-error@+1 {{'ld_arg1a' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg1a(long double ld) {} + +typedef long double ld_ty; +// expected-note@+2 {{'ld_return1b' defined here}} +// expected-error@+1 {{'ld_return1b' requires 128 bit size 'ld_ty' (aka 'long double') type support, but device 'nvptx64-unknown-unknown' does not support it}} +ld_ty ld_return1b() { return 0; } +// expected-note@+2 {{'ld_arg1b' defined here}} +// expected-error@+1 {{'ld_arg1b' requires 128 bit size 'ld_ty' (aka 'long double') type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg1b(ld_ty ld) {} + +static long double ld_return1c() { return 0; } +static void ld_arg1c(long double ld) {} + +inline long double ld_return1d() { return 0; } +inline void ld_arg1d(long double ld) {} + +// expected-note@+1 {{'ld_return1e' defined here}} +static long double ld_return1e() { return 0; } +// expected-note@+1 {{'ld_arg1e' defined here}} +static void ld_arg1e(long double ld) {} + +// expected-note@+1 {{'ld_return1f' defined here}} +inline long double ld_return1f() { return 0; } +// expected-note@+1 {{'ld_arg1f' defined here}} +inline void ld_arg1f(long double ld) {} + +inline void ld_use1() { + long double ld = 0; + ld += 1; +} +static void ld_use2() { + long double ld = 0; + ld += 1; +} + +inline void ld_use3() { +// expected-note@+1 {{'ld' defined here}} + long double ld = 0; +// expected-error@+1 {{'ld' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + ld += 1; +} +static void ld_use4() { +// expected-note@+1 {{'ld' defined here}} + long double ld = 0; +// expected-error@+1 {{'ld' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + ld += 1; +} + +void external() { +// expected-error@+1 {{'ld_return1e' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p1 = reinterpret_cast(&ld_return1e); +// expected-error@+1 {{'ld_arg1e' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p2 = reinterpret_cast(&ld_arg1e); +// expected-error@+1 {{'ld_return1f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p3 = reinterpret_cast(&ld_return1f); +// expected-error@+1 {{'ld_arg1f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p4 = reinterpret_cast(&ld_arg1f); +// TODO: The error message "called by" is not great. +// expected-note@+1 {{called by 'external'}} + void *p5 = reinterpret_cast(&ld_use3); +// expected-note@+1 {{called by 'external'}} + void *p6 = reinterpret_cast(&ld_use4); +} + +#ifndef _ARCH_PPC +// expected-note@+2 {{'ld_return2a' defined here}} +// expected-error@+1 {{'ld_return2a' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +__float128 ld_return2a() { return 0; } +// expected-note@+2 {{'ld_arg2a' defined here}} +// expected-error@+1 {{'ld_arg2a' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg2a(__float128 ld) {} + +typedef __float128 fp128_ty; +// expected-note@+2 {{'ld_return2b' defined here}} +// expected-error@+1 {{'ld_return2b' requires 128 bit size 'fp128_ty' (aka '__float128') type support, but device 'nvptx64-unknown-unknown' does not support it}} +fp128_ty ld_return2b() { return 0; } +// expected-note@+2 {{'ld_arg2b' defined here}} +// expected-error@+1 {{'ld_arg2b' requires 128 bit size 'fp128_ty' (aka '__float128') type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg2b(fp128_ty ld) {} +#endif + #pragma omp end declare target +// TODO: There should not be an error here, dead_inline is never emitted. +// expected-note@+1 {{'f' defined here}} +inline long double dead_inline(long double f) { +#pragma omp target map(f) + // expected-error@+1 {{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + f = 1; + return f; +} + +// TODO: There should not be an error here, dead_static is never emitted. +// expected-note@+1 {{'f' defined here}} +static long double dead_static(long double f) { +#pragma omp target map(f) + // expected-error@+1 {{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + f = 1; + return f; +} + +template +long double dead_template(long double f) { +#pragma omp target map(f) + f = 1; + return f; +} + #ifndef _ARCH_PPC -// expected-note@+1 3{{'f' defined here}} -__float128 foo1(__float128 f) { +// expected-note@+1 {{'f' defined here}} +__float128 foo2(__float128 f) { #pragma omp target map(f) - // expected-error@+1 3{{'f' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} + // expected-error@+1 {{'f' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} f = 1; return f; } #else -// expected-note@+1 3{{'f' defined here}} -long double foo1(long double f) { +// expected-note@+1 {{'f' defined here}} +long double foo3(long double f) { #pragma omp target map(f) - // expected-error@+1 3{{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + // expected-error@+1 {{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} f = 1; return f; } diff --git a/clang/test/OpenMP/target_attribute_convergent.cpp b/clang/test/OpenMP/target_attribute_convergent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..932214e987c8611d84b7f6e0a30a5f86c325c498 --- /dev/null +++ b/clang/test/OpenMP/target_attribute_convergent.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -o - | FileCheck %s +// expected-no-diagnostics + +#pragma omp declare target + +void foo() {} + +#pragma omp end declare target + +// CHECK: Function Attrs: {{.*}}convergent{{.*}} +// CHECK: define hidden void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]] +// CHECK: attributes [[ATTRIBUTE_NUMBER]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp index 0229ace911f87b189cc89d8b420d710a9368b811..c0f53239aa13335f7a60cd3184ba3d20ef1f660a 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp @@ -39,7 +39,7 @@ #ifdef CK1 -// HCK_NO_TGT-NOT: @__kmpc_push_target_tripcount +// HCK_NO_TGT-NOT: @__kmpc_push_target_tripcount_mapper // HCK1: define{{.*}} i32 @{{.+}}target_teams_fun{{.*}}( int target_teams_fun(int *g){ @@ -60,7 +60,7 @@ int target_teams_fun(int *g){ // HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]], // HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // HCK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // HCK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // HCK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, // HCK1: call void @[[OFFL1:.+]](i{{32|64}} [[N_PAR]], {{.+}}, i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]]) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp index 6650e05575110efb1c10dcbd2fde4b2fac2b3aca..efe7df819fb6213353a4def8690c5c6858b445a2 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp @@ -49,10 +49,10 @@ int Arg; // CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test void gtid_test() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( #pragma omp target teams distribute parallel for @@ -107,12 +107,12 @@ int tmain(T Arg) { // CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main() int main() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK-NOT: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK-NOT: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_2:@.+]]( // CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp index b2ab37f22ec33b79d2ae85d2b951381d417b5661..b99ba9d38a43024b6ea7ad8b324fb53f11c31a9d 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp @@ -14,7 +14,7 @@ // CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test void gtid_test() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: %0 = call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 0, i8** null, i8** null, i64* null, i64* null, i8** null, i8** null, i32 0, i32 0) // CHECK: call void [[TARGET_OUTLINE:@.+]]() // CHECK: ret void diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp index e6049145702bcb7fbddef57f5563b04a04c8b385..39ccb87462c02b35b4107ebe1d57c6580de60c4c 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp @@ -60,7 +60,7 @@ int target_teams_fun(int *g){ // HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]], // HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], -// HCK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) +// HCK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // HCK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 5, i8** %{{[^,]+}}, i8** %{{[^,]+}}, // HCK1: call void @[[OFFL1:.+]](i{{32|64}} [[I_PAR]], i{{32|64}} [[N_PAR]], {{.+}}, i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]]) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp index 8b0eaba07f1cbd92c1f848fffd40769fb20d7b3b..19dc15b94f64b50267087d841532a7a60f37e2f5 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp @@ -43,10 +43,10 @@ int Arg; // CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test void gtid_test() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( #ifdef OMP5 @@ -110,12 +110,12 @@ int tmain(T Arg) { // CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main() int main() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK-NOT: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK-NOT: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_2:@.+]]( // CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain diff --git a/clang/test/OpenMP/teams_distribute_codegen.cpp b/clang/test/OpenMP/teams_distribute_codegen.cpp index 5bbb100e669ec4e80f0792534b68324a02c63ca3..aab5cced4c70f910696d8fd143620806e5ac5dc3 100644 --- a/clang/test/OpenMP/teams_distribute_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_codegen.cpp @@ -33,7 +33,7 @@ int teams_argument_global(int n) { // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null, i8** null, i32 {{.+}}, i32 {{.+}}) // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp index b63e5aeddb7a2c0a746b4350ff1bfe8c39c8092b..8fa73e76009bcf1d99396cd662c7b75513448809 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp @@ -32,7 +32,7 @@ int teams_argument_global(int n){ // CK1: [[TH_CAST:%.+]] = alloca i{{32|64}}, // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null, i8** null, i32 {{.+}}, i32 {{.+}}) // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp index 3d479c4cd29dfaa4aa559f65652cbf35d1189f96..9b3855c61759ae88aaf0742264c2e7bbe4d683fd 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp @@ -33,7 +33,7 @@ int teams_argument_global(int n){ // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/OpenMP/teams_distribute_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_codegen.cpp index fd1214d22ce9e04eec184cabbbd07a7cec615eaa..6e5d06b0c5689ea84a840735d3c7dbdba0913708 100644 --- a/clang/test/OpenMP/teams_distribute_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_codegen.cpp @@ -35,7 +35,7 @@ int teams_argument_global(int n) { // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 5, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null, i8** null, i32 {{.+}}, i32 1) // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/Preprocessor/macro_fn_comma_swallow2.c b/clang/test/Preprocessor/macro_fn_comma_swallow2.c index 4e4960ca7f18ceaae579357c4674d27a49066ab5..93ab2b83664a12f837b13b066c927ec36792f2e2 100644 --- a/clang/test/Preprocessor/macro_fn_comma_swallow2.c +++ b/clang/test/Preprocessor/macro_fn_comma_swallow2.c @@ -1,16 +1,11 @@ // Test the __VA_ARGS__ comma swallowing extensions of various compiler dialects. // RUN: %clang_cc1 -E %s | FileCheck -check-prefix=GCC -strict-whitespace %s -// RUN: %clang_cc1 -E -std=c90 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -std=c99 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -std=c11 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -x c++ %s | FileCheck -check-prefix=GCC -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -std=c++03 %s | FileCheck -check-prefix=C99 -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -std=c++11 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -std=gnu99 %s | FileCheck -check-prefix=GCC -strict-whitespace %s // RUN: %clang_cc1 -E -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -std=c++11 -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s // RUN: %clang_cc1 -E -DNAMED %s | FileCheck -check-prefix=GCC -strict-whitespace %s // RUN: %clang_cc1 -E -std=c99 -DNAMED %s | FileCheck -check-prefix=C99 -strict-whitespace %s diff --git a/clang/test/Preprocessor/macro_vaopt_check.cpp b/clang/test/Preprocessor/macro_vaopt_check.cpp index fb52e9946af3dc01a5194644e10fe6aec6feaeb2..c5c0ac518bc0145a6e038e052fe0a05497be3efa 100644 --- a/clang/test/Preprocessor/macro_vaopt_check.cpp +++ b/clang/test/Preprocessor/macro_vaopt_check.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 %s -Eonly -verify -Wno-all -pedantic -std=c++2a +// RUN: %clang_cc1 %s -Eonly -verify -Wno-all -pedantic -std=c++20 +// RUN: %clang_cc1 %s -Eonly -verify -Wno-all -pedantic -std=c++11 +// RUN: %clang_cc1 -x c %s -Eonly -verify -Wno-all -pedantic -std=c99 //expected-error@+1{{missing '('}} #define V1(...) __VA_OPT__ @@ -62,3 +64,11 @@ #define V1(...) __VA_OPT__ ((()) #undef V1 +// __VA_OPT__ can't appear anywhere else. +#if __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}} +#endif + +#ifdef __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}} +#endif + +#define BAD __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}} diff --git a/clang/test/Preprocessor/macro_vaopt_expand.cpp b/clang/test/Preprocessor/macro_vaopt_expand.cpp index 7ec4f6128cfa8526a913c1b032d389263f54e32d..5eb0facb83f7364f2e068e236c70d58dfba6e435 100644 --- a/clang/test/Preprocessor/macro_vaopt_expand.cpp +++ b/clang/test/Preprocessor/macro_vaopt_expand.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -E %s -pedantic -std=c++2a | FileCheck -strict-whitespace %s +// RUN: %clang_cc1 -E %s -pedantic -std=c++20 | FileCheck -strict-whitespace %s +// RUN: %clang_cc1 -E %s -pedantic -std=c++11 | FileCheck -strict-whitespace %s +// RUN: %clang_cc1 -E -x c %s -pedantic -std=c99 | FileCheck -strict-whitespace %s #define LPAREN ( #define RPAREN ) diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 00639550524698996d74c03ae67149de279d7b07..88826bbd60b8259b93399e4b342514b1e56b70c7 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -110,23 +110,23 @@ // CHECK-DOUBLE-NOT: __riscv_float_abi_single // RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions \ -// RUN: -march=rv32iv1p0 -x c -E -dM %s \ +// RUN: -march=rv32iv0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s // RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions \ -// RUN: -march=rv64iv1p0 -x c -E -dM %s \ +// RUN: -march=rv64iv0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// CHECK-V-EXT: __riscv_v 1000000 +// CHECK-V-EXT: __riscv_v 10000 // CHECK-V-EXT: __riscv_vector 1 -// CHECK-V-EXT: __riscv_zvamo 1000000 -// CHECK-V-EXT: __riscv_zvlsseg 1000000 +// CHECK-V-EXT: __riscv_zvamo 10000 +// CHECK-V-EXT: __riscv_zvlsseg 10000 // RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izba0p93 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZBA-EXT %s diff --git a/clang/test/Sema/libbuiltins-ctype-powerpc64.c b/clang/test/Sema/libbuiltins-ctype-powerpc64.c index bfd79acb0ab026e7a2c485c565705d02a730780a..ba0efb205944b3c4fb5c38e79a155eba08617b38 100644 --- a/clang/test/Sema/libbuiltins-ctype-powerpc64.c +++ b/clang/test/Sema/libbuiltins-ctype-powerpc64.c @@ -62,4 +62,4 @@ void test(int x) { // CHECK: declare signext i32 @toupper(i32 signext) [[NUW_RO:#[0-9]+]] // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/Sema/libbuiltins-ctype-x86_64.c b/clang/test/Sema/libbuiltins-ctype-x86_64.c index 4934e6f16752a2015b90bb28d455969348b19fea..b8a2c7e81584a046bceea04abcc776286e30cffe 100644 --- a/clang/test/Sema/libbuiltins-ctype-x86_64.c +++ b/clang/test/Sema/libbuiltins-ctype-x86_64.c @@ -62,4 +62,4 @@ void test(int x) { // CHECK: declare i32 @toupper(i32) [[NUW_RO:#[0-9]+]] // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/Sema/static-assert.c b/clang/test/Sema/static-assert.c index f08e557fc8eab4973f58a707b17e20830e4ed34c..9105f2366985ee05e21f816fef782c2a150fa5f0 100644 --- a/clang/test/Sema/static-assert.c +++ b/clang/test/Sema/static-assert.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-compatibility -DMS -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c99 -pedantic -fsyntax-only -verify=expected,ext %s // RUN: %clang_cc1 -xc++ -std=c++11 -pedantic -fsyntax-only -verify=expected,ext,cxx %s @@ -11,10 +12,17 @@ _Static_assert(1, "1 is nonzero"); // ext-warning {{'_Static_assert' is a C11 ex _Static_assert(0, "0 is nonzero"); // expected-error {{static_assert failed "0 is nonzero"}} \ // ext-warning {{'_Static_assert' is a C11 extension}} +#ifdef MS +static_assert(1, "1 is nonzero"); +#endif + void foo(void) { _Static_assert(1, "1 is nonzero"); // ext-warning {{'_Static_assert' is a C11 extension}} _Static_assert(0, "0 is nonzero"); // expected-error {{static_assert failed "0 is nonzero"}} \ // ext-warning {{'_Static_assert' is a C11 extension}} +#ifdef MS + static_assert(1, "1 is nonzero"); +#endif } _Static_assert(1, invalid); // expected-error {{expected string literal for diagnostic message in static_assert}} \ @@ -25,6 +33,9 @@ struct A { _Static_assert(1, "1 is nonzero"); // ext-warning {{'_Static_assert' is a C11 extension}} _Static_assert(0, "0 is nonzero"); // expected-error {{static_assert failed "0 is nonzero"}} \ // ext-warning {{'_Static_assert' is a C11 extension}} +#ifdef MS + static_assert(1, "1 is nonzero"); +#endif }; #ifdef __cplusplus diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 4adadc9988ab5b8e202499cc89e8b8784aefc2e4..86020a09db443215404578f2f9bdd98192998332 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1437,3 +1437,13 @@ constexpr bool destroy_at_test() { return true; } static_assert(destroy_at_test()); + +namespace PR48582 { + struct S { + void *p = this; + constexpr S() {} + constexpr S(const S&) {} + }; + constexpr bool b = [a = S(), b = S()] { return a.p == b.p; }(); + static_assert(!b); +} diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp index 3647526ff0af715001a5c6e940c9dc1f72a057c7..097ca00640e9a0eae578d183e4e1dd089a0b2c86 100644 --- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp +++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp @@ -176,3 +176,37 @@ constexpr bool construct_after_lifetime_2() { return true; } static_assert(construct_after_lifetime_2()); // expected-error {{}} expected-note {{in call}} + +namespace PR48606 { + struct A { mutable int n = 0; }; + + constexpr bool f() { + A a; + A *p = &a; + p->~A(); + std::construct_at(p); + return true; + } + static_assert(f()); + + constexpr bool g() { + A *p = new A; + p->~A(); + std::construct_at(p); + delete p; + return true; + } + static_assert(g()); + + constexpr bool h() { + std::allocator alloc; + A *p = alloc.allocate(1); + std::construct_at(p); + p->~A(); + std::construct_at(p); + p->~A(); + alloc.deallocate(p); + return true; + } + static_assert(h()); +} diff --git a/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp b/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp index 353360e052bb3c4074fa6f8d00478143c66fddd5..b94225274fffbb7a6ac0bc9d8dd0c90d2d412aaf 100644 --- a/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp +++ b/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -verify %s -Wzero-as-null-pointer-constant // Keep this test before any declarations of operator<=>. namespace PR44786 { @@ -40,3 +40,21 @@ namespace PR47893 { int &f(...); int &r = f(A(), A()); } + +namespace PR44325 { + struct cmp_cat {}; + bool operator<(cmp_cat, void*); + bool operator>(cmp_cat, int cmp_cat::*); + + struct X {}; + cmp_cat operator<=>(X, X); + + bool b1 = X() < X(); // no warning + bool b2 = X() > X(); // no warning + + // FIXME: It's not clear whether warning here is useful, but we can't really + // tell that this is a comparison category in general. This is probably OK, + // as comparisons against zero are only really intended for use in the + // implicit rewrite rules, not for explicit use by programs. + bool c = cmp_cat() < 0; // expected-warning {{zero as null pointer constant}} +} diff --git a/clang/tools/scan-view/CMakeLists.txt b/clang/tools/scan-view/CMakeLists.txt index dd3d33439299afe5c686eb987c498894f0346e78..eccc6b83195b6ea974af60b37a1110a3be148ce7 100644 --- a/clang/tools/scan-view/CMakeLists.txt +++ b/clang/tools/scan-view/CMakeLists.txt @@ -5,6 +5,7 @@ set(BinFiles set(ShareFiles ScanView.py + Reporter.py startfile.py bugcatcher.ico) diff --git a/clang/tools/scan-view/share/Reporter.py b/clang/tools/scan-view/share/Reporter.py new file mode 100644 index 0000000000000000000000000000000000000000..31a14fb0cf74ea619eb5b1a08c04c2e73aa418e7 --- /dev/null +++ b/clang/tools/scan-view/share/Reporter.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""Methods for reporting bugs.""" + +import subprocess, sys, os + +__all__ = ['ReportFailure', 'BugReport', 'getReporters'] + +# + +class ReportFailure(Exception): + """Generic exception for failures in bug reporting.""" + def __init__(self, value): + self.value = value + +# Collect information about a bug. + +class BugReport(object): + def __init__(self, title, description, files): + self.title = title + self.description = description + self.files = files + +# Reporter interfaces. + +import os + +import email, mimetypes, smtplib +from email import encoders +from email.message import Message +from email.mime.base import MIMEBase +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText + +#===------------------------------------------------------------------------===# +# ReporterParameter +#===------------------------------------------------------------------------===# + +class ReporterParameter(object): + def __init__(self, n): + self.name = n + def getName(self): + return self.name + def getValue(self,r,bugtype,getConfigOption): + return getConfigOption(r.getName(),self.getName()) + def saveConfigValue(self): + return True + +class TextParameter (ReporterParameter): + def getHTML(self,r,bugtype,getConfigOption): + return """\ + +%s: + +"""%(self.getName(),r.getName(),self.getName(),self.getValue(r,bugtype,getConfigOption)) + +class SelectionParameter (ReporterParameter): + def __init__(self, n, values): + ReporterParameter.__init__(self,n) + self.values = values + + def getHTML(self,r,bugtype,getConfigOption): + default = self.getValue(r,bugtype,getConfigOption) + return """\ + +%s:"""%(self.getName(),r.getName(),self.getName(),'\n'.join(["""\ +"""%(o[0], + o[0] == default and ' selected="selected"' or '', + o[1]) for o in self.values])) + +#===------------------------------------------------------------------------===# +# Reporters +#===------------------------------------------------------------------------===# + +class EmailReporter(object): + def getName(self): + return 'Email' + + def getParameters(self): + return [TextParameter(x) for x in ['To', 'From', 'SMTP Server', 'SMTP Port']] + + # Lifted from python email module examples. + def attachFile(self, outer, path): + # Guess the content type based on the file's extension. Encoding + # will be ignored, although we should check for simple things like + # gzip'd or compressed files. + ctype, encoding = mimetypes.guess_type(path) + if ctype is None or encoding is not None: + # No guess could be made, or the file is encoded (compressed), so + # use a generic bag-of-bits type. + ctype = 'application/octet-stream' + maintype, subtype = ctype.split('/', 1) + if maintype == 'text': + fp = open(path) + # Note: we should handle calculating the charset + msg = MIMEText(fp.read(), _subtype=subtype) + fp.close() + else: + fp = open(path, 'rb') + msg = MIMEBase(maintype, subtype) + msg.set_payload(fp.read()) + fp.close() + # Encode the payload using Base64 + encoders.encode_base64(msg) + # Set the filename parameter + msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(path)) + outer.attach(msg) + + def fileReport(self, report, parameters): + mainMsg = """\ +BUG REPORT +--- +Title: %s +Description: %s +"""%(report.title, report.description) + + if not parameters.get('To'): + raise ReportFailure('No "To" address specified.') + if not parameters.get('From'): + raise ReportFailure('No "From" address specified.') + + msg = MIMEMultipart() + msg['Subject'] = 'BUG REPORT: %s'%(report.title) + # FIXME: Get config parameters + msg['To'] = parameters.get('To') + msg['From'] = parameters.get('From') + msg.preamble = mainMsg + + msg.attach(MIMEText(mainMsg, _subtype='text/plain')) + for file in report.files: + self.attachFile(msg, file) + + try: + s = smtplib.SMTP(host=parameters.get('SMTP Server'), + port=parameters.get('SMTP Port')) + s.sendmail(msg['From'], msg['To'], msg.as_string()) + s.close() + except: + raise ReportFailure('Unable to send message via SMTP.') + + return "Message sent!" + +class BugzillaReporter(object): + def getName(self): + return 'Bugzilla' + + def getParameters(self): + return [TextParameter(x) for x in ['URL','Product']] + + def fileReport(self, report, parameters): + raise NotImplementedError + + +class RadarClassificationParameter(SelectionParameter): + def __init__(self): + SelectionParameter.__init__(self,"Classification", + [['1', 'Security'], ['2', 'Crash/Hang/Data Loss'], + ['3', 'Performance'], ['4', 'UI/Usability'], + ['6', 'Serious Bug'], ['7', 'Other']]) + + def saveConfigValue(self): + return False + + def getValue(self,r,bugtype,getConfigOption): + if bugtype.find("leak") != -1: + return '3' + elif bugtype.find("dereference") != -1: + return '2' + elif bugtype.find("missing ivar release") != -1: + return '3' + else: + return '7' + +### + +def getReporters(): + reporters = [] + reporters.append(EmailReporter()) + return reporters + diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 92bf244b0e4afc07abb1896398dae61dbd1ae220..06c2bbc29e5c58ecfe57b169f3c3a2e6f4f4aeac 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -474,6 +474,42 @@ TEST(Matcher, CapturesThis) { EXPECT_TRUE(notMatches("void f() { int z = 3; [&z](){}; }", HasCaptureThis)); } +TEST(Matcher, MatchesMethodsOnLambda) { + StringRef Code = R"cpp( +struct A { + ~A() {} +}; +void foo() +{ + A a; + auto l = [a] { }; + auto lCopy = l; + auto lPtrDecay = +[] { }; + (void)lPtrDecay; +} +)cpp"; + + EXPECT_TRUE(matches( + Code, cxxConstructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))), + isCopyConstructor()))); + EXPECT_TRUE(matches( + Code, cxxConstructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))), + isMoveConstructor()))); + EXPECT_TRUE(matches( + Code, cxxDestructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l")))))))); + EXPECT_TRUE(matches( + Code, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt( + hasReturnValue(implicitCastExpr()))))), + hasAncestor(lambdaExpr(hasAncestor( + varDecl(hasName("lPtrDecay")))))))); +} + TEST(Matcher, isClassMessage) { EXPECT_TRUE(matchesObjC( "@interface NSString +(NSString *) stringWithFormat; @end " @@ -2483,6 +2519,78 @@ template<> bool timesTwo(bool){ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } + + Code = R"cpp( +struct B { + B(int); +}; + +B func1() { return 42; } + )cpp"; + { + auto M = expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(unless(integerLiteral(equals(24)))).bind("intLit"); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 7))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = + expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr()))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr())); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(integerLiteral(equals(42)).bind("intLit"), expr()); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(optionally(integerLiteral(equals(42)).bind("intLit"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr().bind("allExprs"); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("allExprs", 7))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("allExprs", 1))); + } } TEST(Traversal, traverseNoImplicit) { @@ -2784,6 +2892,36 @@ struct CtorInitsNonTrivial : NonTrivial EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } + Code = R"cpp( + struct Range { + int* begin() const; + int* end() const; + }; + Range getRange(int); + + void rangeFor() + { + for (auto i : getRange(42)) + { + } + } + )cpp"; + { + auto M = integerLiteral(equals(42)); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + { + auto M = callExpr(hasDescendant(integerLiteral(equals(42)))); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + { + auto M = compoundStmt(hasDescendant(integerLiteral(equals(42)))); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + Code = R"cpp( void rangeFor() { @@ -2855,6 +2993,40 @@ struct CtorInitsNonTrivial : NonTrivial matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), true, {"-std=c++20"})); } + + Code = R"cpp( + struct Range { + int* begin() const; + int* end() const; + }; + Range getRange(int); + + int getNum(int); + + void rangeFor() + { + for (auto j = getNum(42); auto i : getRange(j)) + { + } + } + )cpp"; + { + auto M = integerLiteral(equals(42)); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"})); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + true, {"-std=c++20"})); + } + { + auto M = compoundStmt(hasDescendant(integerLiteral(equals(42)))); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"})); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + true, {"-std=c++20"})); + } + Code = R"cpp( void hasDefaultArg(int i, int j = 0) { @@ -3120,6 +3292,12 @@ void func14() { float i = 42.0; } +void func15() { + int count = 0; + auto l = [&] { ++count; }; + (void)l; +} + )cpp"; EXPECT_TRUE( @@ -3304,6 +3482,15 @@ void func14() { functionDecl(hasName("func14"), hasDescendant(floatLiteral()))), langCxx20OrLater())); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + compoundStmt( + hasDescendant(varDecl(hasName("count")).bind("countVar")), + hasDescendant( + declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))), + langCxx20OrLater())); + Code = R"cpp( void foo() { int explicit_captured = 0; @@ -3853,6 +4040,78 @@ void binop() } } +TEST(IgnoringImpCasts, PathologicalLambda) { + + // Test that deeply nested lambdas are not a performance penalty + StringRef Code = R"cpp( +void f() { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + int i = 42; + (void)i; + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); +} + )cpp"; + + EXPECT_TRUE(matches(Code, integerLiteral(equals(42)))); + EXPECT_TRUE(matches(Code, functionDecl(hasDescendant(integerLiteral(equals(42)))))); +} + TEST(IgnoringImpCasts, MatchesImpCasts) { // This test checks that ignoringImpCasts matches when implicit casts are // present and its inner matcher alone does not match. diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 855cf0242fe973f177c76f0f09dc2dc640e4a5f0..45278fdb69e65b4ea0216ab0c6a5d43f649056fa 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10248,6 +10248,21 @@ TEST_F(FormatTest, SplitEmptyClass) { "{\n" "};", Style); + + verifyFormat("#include \"stdint.h\"\n" + "namespace rep {}", + Style); + verifyFormat("#include \n" + "namespace rep {}", + Style); + verifyFormat("#include \n" + "namespace rep {}", + "#include \n" + "namespace rep {\n" + "\n" + "\n" + "}", + Style); } TEST_F(FormatTest, SplitEmptyStruct) { @@ -12353,6 +12368,17 @@ TEST_F(FormatTest, ConfigurableSpacesInParentheses) { verifyFormat("size_t idx = (a->*foo)(a - 1);", Spaces); verifyFormat("size_t idx = (a->foo)(a - 1);", Spaces); verifyFormat("size_t idx = (*foo)(a - 1);", Spaces); + verifyFormat("size_t idx = (*(foo))(a - 1);", Spaces); + Spaces.ColumnLimit = 80; + Spaces.IndentWidth = 4; + Spaces.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + verifyFormat("void foo( ) {\n" + " size_t foo = (*(function))(\n" + " Foooo, Barrrrr, Foooo, Barrrr, FoooooooooLooooong, " + "BarrrrrrrrrrrrLong,\n" + " FoooooooooLooooong);\n" + "}", + Spaces); Spaces.SpaceAfterCStyleCast = false; verifyFormat("size_t idx = (size_t)(ptr - ((char *)file));", Spaces); verifyFormat("size_t idx = (size_t)a;", Spaces); @@ -12360,6 +12386,15 @@ TEST_F(FormatTest, ConfigurableSpacesInParentheses) { verifyFormat("size_t idx = (a->*foo)(a - 1);", Spaces); verifyFormat("size_t idx = (a->foo)(a - 1);", Spaces); verifyFormat("size_t idx = (*foo)(a - 1);", Spaces); + verifyFormat("size_t idx = (*(foo))(a - 1);", Spaces); + + verifyFormat("void foo( ) {\n" + " size_t foo = (*(function))(\n" + " Foooo, Barrrrr, Foooo, Barrrr, FoooooooooLooooong, " + "BarrrrrrrrrrrrLong,\n" + " FoooooooooLooooong);\n" + "}", + Spaces); } TEST_F(FormatTest, ConfigurableSpacesInSquareBrackets) { @@ -14706,6 +14741,7 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { WhitesmithsBraceStyle); */ + WhitesmithsBraceStyle.NamespaceIndentation = FormatStyle::NI_None; verifyFormat("namespace a\n" " {\n" "class A\n" @@ -14730,6 +14766,89 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { " } // namespace a", WhitesmithsBraceStyle); + verifyFormat("namespace a\n" + " {\n" + "namespace b\n" + " {\n" + "class A\n" + " {\n" + " void f()\n" + " {\n" + " if (true)\n" + " {\n" + " a();\n" + " b();\n" + " }\n" + " }\n" + " void g()\n" + " {\n" + " return;\n" + " }\n" + " };\n" + "struct B\n" + " {\n" + " int x;\n" + " };\n" + " } // namespace b\n" + " } // namespace a", + WhitesmithsBraceStyle); + + WhitesmithsBraceStyle.NamespaceIndentation = FormatStyle::NI_Inner; + verifyFormat("namespace a\n" + " {\n" + "namespace b\n" + " {\n" + " class A\n" + " {\n" + " void f()\n" + " {\n" + " if (true)\n" + " {\n" + " a();\n" + " b();\n" + " }\n" + " }\n" + " void g()\n" + " {\n" + " return;\n" + " }\n" + " };\n" + " struct B\n" + " {\n" + " int x;\n" + " };\n" + " } // namespace b\n" + " } // namespace a", + WhitesmithsBraceStyle); + + WhitesmithsBraceStyle.NamespaceIndentation = FormatStyle::NI_All; + verifyFormat("namespace a\n" + " {\n" + " namespace b\n" + " {\n" + " class A\n" + " {\n" + " void f()\n" + " {\n" + " if (true)\n" + " {\n" + " a();\n" + " b();\n" + " }\n" + " }\n" + " void g()\n" + " {\n" + " return;\n" + " }\n" + " };\n" + " struct B\n" + " {\n" + " int x;\n" + " };\n" + " } // namespace b\n" + " } // namespace a", + WhitesmithsBraceStyle); + verifyFormat("void f()\n" " {\n" " if (true)\n" @@ -14764,7 +14883,7 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { " }\n", WhitesmithsBraceStyle); - WhitesmithsBraceStyle.IndentCaseBlocks = true; + WhitesmithsBraceStyle.IndentCaseLabels = true; verifyFormat("void switchTest1(int a)\n" " {\n" " switch (a)\n" @@ -14772,7 +14891,7 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { " case 2:\n" " {\n" " }\n" - " break;\n" + " break;\n" " }\n" " }\n", WhitesmithsBraceStyle); @@ -14782,7 +14901,7 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { " switch (a)\n" " {\n" " case 0:\n" - " break;\n" + " break;\n" " case 1:\n" " {\n" " break;\n" @@ -14790,9 +14909,9 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { " case 2:\n" " {\n" " }\n" - " break;\n" + " break;\n" " default:\n" - " break;\n" + " break;\n" " }\n" " }\n", WhitesmithsBraceStyle); @@ -14805,17 +14924,17 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { " {\n" " foo(x);\n" " }\n" - " break;\n" + " break;\n" " default:\n" " {\n" " foo(1);\n" " }\n" - " break;\n" + " break;\n" " }\n" " }\n", WhitesmithsBraceStyle); - WhitesmithsBraceStyle.IndentCaseBlocks = false; + WhitesmithsBraceStyle.IndentCaseLabels = false; verifyFormat("void switchTest4(int a)\n" " {\n" diff --git a/clang/unittests/Sema/CodeCompleteTest.cpp b/clang/unittests/Sema/CodeCompleteTest.cpp index d8b303d77bb9643de67de960071b50ef211fbf73..dae0793658c5bf9fdb9381120995c956cb444a19 100644 --- a/clang/unittests/Sema/CodeCompleteTest.cpp +++ b/clang/unittests/Sema/CodeCompleteTest.cpp @@ -488,6 +488,7 @@ TEST(PreferredTypeTest, NoCrashOnInvalidTypes) { auto y = new decltype(&1)(^); // GNU decimal type extension is not supported in clang. auto z = new _Decimal128(^); + void foo() { (void)(foo)(^); } )cpp"; EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE")); } diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 685f32dbe0d3a6b4d29504bb1c5888e814dd67c7..fc3340ec9d963f53f84a86c8a872a9251c0ed8b8 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1005,7 +1005,7 @@ ISO C++ 2020 Draft International Standard. Class types as non-type template parameters P0732R2 - Clang 12 + Partial P1907R1 diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index b511a9a987b3f86586a584a4428213c609f95ed7..73b6bead84245394e61586caa58f840e2763b237 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -515,6 +515,12 @@ set(aarch64_SOURCES set(OA_HELPERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/outline_atomic_helpers.dir") file(MAKE_DIRECTORY "${OA_HELPERS_DIR}") +if(CMAKE_HOST_UNIX) + set(COMPILER_RT_LINK_OR_COPY create_symlink) +else() + set(COMPILER_RT_LINK_OR_COPY copy) +endif() + foreach(pat cas swp ldadd ldclr ldeor ldset) foreach(size 1 2 4 8 16) foreach(model 1 2 3 4) @@ -522,7 +528,7 @@ foreach(pat cas swp ldadd ldclr ldeor ldset) set(helper_asm "${OA_HELPERS_DIR}/outline_atomic_${pat}${size}_${model}.S") add_custom_command( OUTPUT ${helper_asm} - COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/aarch64/lse.S" "${helper_asm}" + COMMAND ${CMAKE_COMMAND} -E ${COMPILER_RT_LINK_OR_COPY} "${CMAKE_CURRENT_SOURCE_DIR}/aarch64/lse.S" "${helper_asm}" ) set_source_files_properties("${helper_asm}" PROPERTIES diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp index 7378b237a71175ebfbd5a126e1f45cb1a9336412..5dc9090f36c0fb07274fb9bfb630da2181ee6612 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cpp +++ b/compiler-rt/lib/msan/tests/msan_test.cpp @@ -3707,7 +3707,9 @@ TEST(MemorySanitizer, getgrent_r) { EXPECT_NOT_POISONED(grp.gr_gid); EXPECT_NOT_POISONED(grpres); } +#endif +#ifdef __GLIBC__ TEST(MemorySanitizer, fgetgrent_r) { FILE *fp = fopen("/etc/group", "r"); struct group grp; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc index 7f181258eab52b11688d6857ddfe09acc98ba986..b7da659875574ed3ca457780799d5b4c556d2f68 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc @@ -370,15 +370,6 @@ static void ioctl_table_fill() { #if SANITIZER_GLIBC // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE - _(CYGETDEFTHRESH, WRITE, sizeof(int)); - _(CYGETDEFTIMEOUT, WRITE, sizeof(int)); - _(CYGETMON, WRITE, struct_cyclades_monitor_sz); - _(CYGETTHRESH, WRITE, sizeof(int)); - _(CYGETTIMEOUT, WRITE, sizeof(int)); - _(CYSETDEFTHRESH, NONE, 0); - _(CYSETDEFTIMEOUT, NONE, 0); - _(CYSETTHRESH, NONE, 0); - _(CYSETTIMEOUT, NONE, 0); _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz); _(EQL_ENSLAVE, WRITE, struct_ifreq_sz); _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 7f7b38d4215b1ae2bc2ee48e3255f1b07a7c01cb..068fc9829e57db3f6056a04d13d936e49877beb7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -226,7 +226,7 @@ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_GETPWENT \ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) -#define SANITIZER_INTERCEPT_FGETGRENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS) +#define SANITIZER_INTERCEPT_FGETGRENT_R (SI_GLIBC || SI_SOLARIS) #define SANITIZER_INTERCEPT_FGETPWENT SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_GETPWENT_R \ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index 12dd39e674ac84f71fa450e3112c40ec71036b03..7abaeb880bf347dee2490b1eb8b0295adfa8bb9c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -143,7 +143,6 @@ typedef struct user_fpregs elf_fpregset_t; # include #endif #include -#include #include #include #include @@ -459,7 +458,6 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); #if SANITIZER_GLIBC unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct); - unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor); #if EV_VERSION > (0x010000) unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry); #else @@ -823,15 +821,6 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); #endif // SANITIZER_LINUX #if SANITIZER_LINUX && !SANITIZER_ANDROID - unsigned IOCTL_CYGETDEFTHRESH = CYGETDEFTHRESH; - unsigned IOCTL_CYGETDEFTIMEOUT = CYGETDEFTIMEOUT; - unsigned IOCTL_CYGETMON = CYGETMON; - unsigned IOCTL_CYGETTHRESH = CYGETTHRESH; - unsigned IOCTL_CYGETTIMEOUT = CYGETTIMEOUT; - unsigned IOCTL_CYSETDEFTHRESH = CYSETDEFTHRESH; - unsigned IOCTL_CYSETDEFTIMEOUT = CYSETDEFTIMEOUT; - unsigned IOCTL_CYSETTHRESH = CYSETTHRESH; - unsigned IOCTL_CYSETTIMEOUT = CYSETTIMEOUT; unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE; unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE; unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 836b178c131ba03680eeaaaf04aeb1848c90564b..8a156b7fcb80aed32fdeaf773c4ca3e60d3dc97a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -983,7 +983,6 @@ extern unsigned struct_vt_mode_sz; #if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned struct_ax25_parms_struct_sz; -extern unsigned struct_cyclades_monitor_sz; extern unsigned struct_input_keymap_entry_sz; extern unsigned struct_ipx_config_data_sz; extern unsigned struct_kbdiacrs_sz; @@ -1328,15 +1327,6 @@ extern unsigned IOCTL_VT_WAITACTIVE; #endif // SANITIZER_LINUX #if SANITIZER_LINUX && !SANITIZER_ANDROID -extern unsigned IOCTL_CYGETDEFTHRESH; -extern unsigned IOCTL_CYGETDEFTIMEOUT; -extern unsigned IOCTL_CYGETMON; -extern unsigned IOCTL_CYGETTHRESH; -extern unsigned IOCTL_CYGETTIMEOUT; -extern unsigned IOCTL_CYSETDEFTHRESH; -extern unsigned IOCTL_CYSETDEFTIMEOUT; -extern unsigned IOCTL_CYSETTHRESH; -extern unsigned IOCTL_CYSETTIMEOUT; extern unsigned IOCTL_EQL_EMANCIPATE; extern unsigned IOCTL_EQL_ENSLAVE; extern unsigned IOCTL_EQL_GETMASTRCFG; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp index d29438cf9dbd59416ea3c0cb03433de4eed3ebbc..12603da1750d155c0b4bc525411b1bcb485da57c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -165,7 +165,12 @@ bool SupportsColoredOutput(fd_t fd) { #if !SANITIZER_GO // TODO(glider): different tools may require different altstack size. -static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. +static uptr GetAltStackSize() { + // Note: since GLIBC_2.31, SIGSTKSZ may be a function call, so this may be + // more costly that you think. However GetAltStackSize is only call 2-3 times + // per thread so don't cache the evaluation. + return SIGSTKSZ * 4; +} void SetAlternateSignalStack() { stack_t altstack, oldstack; @@ -176,10 +181,10 @@ void SetAlternateSignalStack() { // TODO(glider): the mapped stack should have the MAP_STACK flag in the // future. It is not required by man 2 sigaltstack now (they're using // malloc()). - void* base = MmapOrDie(kAltStackSize, __func__); + void *base = MmapOrDie(GetAltStackSize(), __func__); altstack.ss_sp = (char*) base; altstack.ss_flags = 0; - altstack.ss_size = kAltStackSize; + altstack.ss_size = GetAltStackSize(); CHECK_EQ(0, sigaltstack(&altstack, nullptr)); } @@ -187,7 +192,7 @@ void UnsetAlternateSignalStack() { stack_t altstack, oldstack; altstack.ss_sp = nullptr; altstack.ss_flags = SS_DISABLE; - altstack.ss_size = kAltStackSize; // Some sane value required on Darwin. + altstack.ss_size = GetAltStackSize(); // Some sane value required on Darwin. CHECK_EQ(0, sigaltstack(&altstack, &oldstack)); UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); } diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 4e7e8f97854622d1619c271a4389b588c05dd606..cdd5495e36ab02da2bda36ac317a38f8132f6eb5 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -29,7 +29,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXX_STANDALONE_BUIL project(libcxx CXX C) set(PACKAGE_NAME libcxx) - set(PACKAGE_VERSION 12.0.0git) + set(PACKAGE_VERSION 12.0.1) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libcxx/cmake/Modules/HandleLibCXXABI.cmake b/libcxx/cmake/Modules/HandleLibCXXABI.cmake index c5aa26739e3672d9b901b91be5f4cc6bc2789dbd..5d2764e870e99b8c34462e72dafd886bbe8642d2 100644 --- a/libcxx/cmake/Modules/HandleLibCXXABI.cmake +++ b/libcxx/cmake/Modules/HandleLibCXXABI.cmake @@ -121,6 +121,8 @@ elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt") if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS) set(LIBCXX_CXX_ABI_INCLUDE_PATHS "/usr/include/c++/v1") endif() + # libcxxrt does not provide aligned new and delete operators + set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON) setup_abi_lib( "-DLIBCXXRT" "cxxrt" "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" "" diff --git a/libcxx/cmake/caches/FreeBSD.cmake b/libcxx/cmake/caches/FreeBSD.cmake new file mode 100644 index 0000000000000000000000000000000000000000..9e66e379864b66dc387275ca7091c70f8a323aa3 --- /dev/null +++ b/libcxx/cmake/caches/FreeBSD.cmake @@ -0,0 +1,9 @@ +set(CMAKE_BUILD_TYPE Release CACHE STRING "") +set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "") + +set(LIBCXX_ENABLE_ASSERTIONS OFF CACHE BOOL "") +set(LIBCXX_ABI_VERSION "1" CACHE STRING "") +set(LIBCXX_ENABLE_STATIC ON CACHE BOOL "") +set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "") +set(LIBCXX_CXX_ABI libcxxrt CACHE STRING "") +set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "") diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 77e5e556d68464868453accf5c52e518a35f569f..29a317b8ae9a4634e8297c017729dde5e3bf5a44 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -150,25 +150,25 @@ set(files string.h string_view strstream - support/android/locale_bionic.h - support/fuchsia/xlocale.h - support/ibm/limits.h - support/ibm/locale_mgmt_aix.h - support/ibm/nanosleep.h - support/ibm/support.h - support/ibm/xlocale.h - support/musl/xlocale.h - support/newlib/xlocale.h - support/nuttx/xlocale.h - support/openbsd/xlocale.h - support/solaris/floatingpoint.h - support/solaris/wchar.h - support/solaris/xlocale.h - support/win32/limits_msvc_win32.h - support/win32/locale_win32.h - support/xlocale/__nop_locale_mgmt.h - support/xlocale/__posix_l_fallback.h - support/xlocale/__strtonum_fallback.h + __support/android/locale_bionic.h + __support/fuchsia/xlocale.h + __support/ibm/limits.h + __support/ibm/locale_mgmt_aix.h + __support/ibm/nanosleep.h + __support/ibm/support.h + __support/ibm/xlocale.h + __support/musl/xlocale.h + __support/newlib/xlocale.h + __support/nuttx/xlocale.h + __support/openbsd/xlocale.h + __support/solaris/floatingpoint.h + __support/solaris/wchar.h + __support/solaris/xlocale.h + __support/win32/limits_msvc_win32.h + __support/win32/locale_win32.h + __support/xlocale/__nop_locale_mgmt.h + __support/xlocale/__posix_l_fallback.h + __support/xlocale/__strtonum_fallback.h system_error tgmath.h thread diff --git a/libcxx/include/__availability b/libcxx/include/__availability index db2267c8eb16fea9ad477b0d6ce675e181a3bbdc..cc3b6fabdab1726c5efbd49c507ce6376b715acf 100644 --- a/libcxx/include/__availability +++ b/libcxx/include/__availability @@ -43,6 +43,14 @@ // as unavailable. When vendors decide to ship the feature as part of their // shared library, they can update the markup appropriately. // +// Furthermore, many features in the standard library have corresponding +// feature-test macros. When a feature is made unavailable on some deployment +// target, a macro should be defined to signal that it is unavailable. That +// macro can then be picked up when feature-test macros are generated (see +// generate_feature_test_macro_components.py) to make sure that feature-test +// macros don't announce a feature as being implemented if it has been marked +// as unavailable. +// // Note that this mechanism is disabled by default in the "upstream" libc++. // Availability annotations are only meaningful when shipping libc++ inside // a platform (i.e. as a system library), and so vendors that want them should @@ -76,6 +84,8 @@ // This controls the availability of std::shared_mutex and std::shared_timed_mutex, // which were added to the dylib later. # define _LIBCPP_AVAILABILITY_SHARED_MUTEX +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex // These macros control the availability of std::bad_optional_access and // other exception types. These were put in the shared library to prevent @@ -114,6 +124,7 @@ # define _LIBCPP_AVAILABILITY_FILESYSTEM # define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH # define _LIBCPP_AVAILABILITY_FILESYSTEM_POP +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem // This controls the availability of std::to_chars. # define _LIBCPP_AVAILABILITY_TO_CHARS @@ -122,6 +133,10 @@ // which requires shared library support for various operations // (see libcxx/src/atomic.cpp). # define _LIBCPP_AVAILABILITY_SYNC +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch +// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore #elif defined(__APPLE__) @@ -130,6 +145,14 @@ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex +# endif + # define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \ __attribute__((availability(macosx,strict,introduced=10.13))) \ __attribute__((availability(ios,strict,introduced=11.0))) \ @@ -139,27 +162,34 @@ _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS # define _LIBCPP_AVAILABILITY_BAD_ANY_CAST \ _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS + # define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \ __attribute__((availability(macosx,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) + # define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE \ __attribute__((availability(macosx,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) + # define _LIBCPP_AVAILABILITY_FUTURE_ERROR \ __attribute__((availability(ios,strict,introduced=6.0))) + # define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE \ __attribute__((availability(macosx,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + # define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY \ __attribute__((availability(macosx,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + # define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \ __attribute__((availability(macosx,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + # define _LIBCPP_AVAILABILITY_FILESYSTEM \ __attribute__((availability(macosx,strict,introduced=10.15))) \ __attribute__((availability(ios,strict,introduced=13.0))) \ @@ -175,10 +205,23 @@ _Pragma("clang attribute pop") \ _Pragma("clang attribute pop") \ _Pragma("clang attribute pop") +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem +# endif + # define _LIBCPP_AVAILABILITY_TO_CHARS \ _LIBCPP_AVAILABILITY_FILESYSTEM + + // Note: Those are not ABI-stable yet, so we can't ship them. # define _LIBCPP_AVAILABILITY_SYNC \ __attribute__((unavailable)) +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch +# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore #else diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 9cfb4b84e6535adbd948c9d789e6c44033f74de1..d44ad03d31345af48e470caedaae1fb773224ab7 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -1114,28 +1114,26 @@ public: #endif {} - // avoid re-declaring a copy constructor for the non-const version. - using __type_for_copy_to_const = - _If<_IsConst, __bit_iterator<_Cp, false>, struct __private_nat>; - + // When _IsConst=false, this is the copy constructor. + // It is non-trivial. Making it trivial would break ABI. + // When _IsConst=true, this is a converting constructor; + // the copy and move constructors are implicitly generated + // and trivial. _LIBCPP_INLINE_VISIBILITY - __bit_iterator(const __type_for_copy_to_const& __it) _NOEXCEPT + __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} - // The non-const __bit_iterator has historically had a non-trivial - // copy constructor (as a quirk of its construction). We need to maintain - // this for ABI purposes. - using __type_for_abi_non_trivial_copy_ctor = - _If; - - _LIBCPP_INLINE_VISIBILITY - __bit_iterator(__type_for_abi_non_trivial_copy_ctor const& __it) _NOEXCEPT - : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} - - // Always declare the copy assignment operator since the implicit declaration - // is deprecated. + // When _IsConst=false, we have a user-provided copy constructor, + // so we must also provide a copy assignment operator because + // the implicit generation of a defaulted one is deprecated. + // When _IsConst=true, the assignment operators are + // implicitly generated and trivial. _LIBCPP_INLINE_VISIBILITY - __bit_iterator& operator=(__bit_iterator const&) = default; + __bit_iterator& operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) { + __seg_ = __it.__seg_; + __ctz_ = __it.__ctz_; + return *this; + } _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT {return reference(__seg_, __storage_type(1) << __ctz_);} diff --git a/libcxx/include/__locale b/libcxx/include/__locale index a2da7d78049fcabd1054702690205f41ab7d731b..77e5faab2676ddf2b75f56a9a0f88fa14af23b53 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -21,30 +21,30 @@ #include #if defined(_LIBCPP_MSVCRT_LIKE) # include -# include +# include <__support/win32/locale_win32.h> #elif defined(__NuttX__) -# include +# include <__support/nuttx/xlocale.h> #elif defined(_AIX) || defined(__MVS__) -# include +# include <__support/ibm/xlocale.h> #elif defined(__ANDROID__) -# include +# include <__support/android/locale_bionic.h> #elif defined(__sun__) # include -# include +# include <__support/solaris/xlocale.h> #elif defined(_NEWLIB_VERSION) -# include +# include <__support/newlib/xlocale.h> #elif defined(__OpenBSD__) -# include +# include <__support/openbsd/xlocale.h> #elif (defined(__APPLE__) || defined(__FreeBSD__) \ || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) # include #elif defined(__Fuchsia__) -# include +# include <__support/fuchsia/xlocale.h> #elif defined(__wasi__) // WASI libc uses musl's locales support. -# include +# include <__support/musl/xlocale.h> #elif defined(_LIBCPP_HAS_MUSL_LIBC) -# include +# include <__support/musl/xlocale.h> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/support/android/locale_bionic.h b/libcxx/include/__support/android/locale_bionic.h similarity index 90% rename from libcxx/include/support/android/locale_bionic.h rename to libcxx/include/__support/android/locale_bionic.h index f05a6a0522ca2c45822b70aca8316df6bdc54707..8c6d4bd0dc32287bfc5f7407a971314fb8f47794 100644 --- a/libcxx/include/support/android/locale_bionic.h +++ b/libcxx/include/__support/android/locale_bionic.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/android/locale_bionic.h ------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -28,13 +28,13 @@ extern "C" { #include #include #if __ANDROID_API__ < 21 -#include +#include <__support/xlocale/__posix_l_fallback.h> #endif // In NDK versions later than 16, locale-aware functions are provided by // legacy_stdlib_inlines.h #if __NDK_MAJOR__ <= 16 #if __ANDROID_API__ < 21 -#include +#include <__support/xlocale/__strtonum_fallback.h> #elif __ANDROID_API__ < 26 #if defined(__cplusplus) diff --git a/libcxx/include/support/fuchsia/xlocale.h b/libcxx/include/__support/fuchsia/xlocale.h similarity index 74% rename from libcxx/include/support/fuchsia/xlocale.h rename to libcxx/include/__support/fuchsia/xlocale.h index b86ce9efbd116d9d8d0366a51248c79090bae3d0..e8def81480eaecd3b790dab0cfe4b4dcd435b281 100644 --- a/libcxx/include/support/fuchsia/xlocale.h +++ b/libcxx/include/__support/fuchsia/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/fuchsia/xlocale.h ------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,8 +14,8 @@ #include #include -#include -#include +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> #endif // defined(__Fuchsia__) diff --git a/libcxx/include/support/ibm/limits.h b/libcxx/include/__support/ibm/limits.h similarity index 97% rename from libcxx/include/support/ibm/limits.h rename to libcxx/include/__support/ibm/limits.h index d1c59f066a879aace4aa7d7ccad189ca3c193233..45f1f1e3684ca349aa9a38156cab68c3380a95d0 100644 --- a/libcxx/include/support/ibm/limits.h +++ b/libcxx/include/__support/ibm/limits.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------- support/ibm/limits.h ---------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/ibm/locale_mgmt_aix.h b/libcxx/include/__support/ibm/locale_mgmt_aix.h similarity index 96% rename from libcxx/include/support/ibm/locale_mgmt_aix.h rename to libcxx/include/__support/ibm/locale_mgmt_aix.h index e452dc32529de2eeb0fd6f1ff6488009a7b38d98..4f658c3eee3065e655234e50901e8dc2e8f0b73b 100644 --- a/libcxx/include/support/ibm/locale_mgmt_aix.h +++ b/libcxx/include/__support/ibm/locale_mgmt_aix.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/ibm/locale_mgmt_aix.h --------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/ibm/nanosleep.h b/libcxx/include/__support/ibm/nanosleep.h similarity index 100% rename from libcxx/include/support/ibm/nanosleep.h rename to libcxx/include/__support/ibm/nanosleep.h diff --git a/libcxx/include/support/ibm/support.h b/libcxx/include/__support/ibm/support.h similarity index 95% rename from libcxx/include/support/ibm/support.h rename to libcxx/include/__support/ibm/support.h index 0569cbe7460df4134863614a3db951ff8dc792a0..a7751b017666793b246f93f9d0c7f25ebf77b0dc 100644 --- a/libcxx/include/support/ibm/support.h +++ b/libcxx/include/__support/ibm/support.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===----------------------- support/ibm/support.h ----------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/ibm/xlocale.h b/libcxx/include/__support/ibm/xlocale.h similarity index 97% rename from libcxx/include/support/ibm/xlocale.h rename to libcxx/include/__support/ibm/xlocale.h index fde137cde260f655a0ff1c4fc762609fea0cfb0c..ad07a255fc951fdadf5e611d37dbc2287058b44f 100644 --- a/libcxx/include/support/ibm/xlocale.h +++ b/libcxx/include/__support/ibm/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------- support/ibm/xlocale.h -------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,7 +9,8 @@ #ifndef _LIBCPP_SUPPORT_IBM_XLOCALE_H #define _LIBCPP_SUPPORT_IBM_XLOCALE_H -#include + +#include <__support/ibm/locale_mgmt_aix.h> #include "cstdlib" @@ -218,7 +219,7 @@ size_t strftime_l(char *__s, size_t __size, const char *__fmt, #elif defined(__MVS__) #include // POSIX routines -#include +#include <__support/xlocale/__posix_l_fallback.h> #endif // defined(__MVS__) // The following are not POSIX routines. These are quick-and-dirty hacks diff --git a/libcxx/include/support/musl/xlocale.h b/libcxx/include/__support/musl/xlocale.h similarity index 95% rename from libcxx/include/support/musl/xlocale.h rename to libcxx/include/__support/musl/xlocale.h index 722d13fa1d665686611c19f0ed3efabbb1631f97..2508a8e8e0ca5714a328df83cb3f1479625c9022 100644 --- a/libcxx/include/support/musl/xlocale.h +++ b/libcxx/include/__support/musl/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/musl/xlocale.h ------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/newlib/xlocale.h b/libcxx/include/__support/newlib/xlocale.h similarity index 82% rename from libcxx/include/support/newlib/xlocale.h rename to libcxx/include/__support/newlib/xlocale.h index 25fa798b6d029f440d77a066f299325ae0a4d7b9..b75f9263a4c40857685a891b0b4b1fdc1e52fd3d 100644 --- a/libcxx/include/support/newlib/xlocale.h +++ b/libcxx/include/__support/newlib/xlocale.h @@ -17,9 +17,9 @@ #include #if !defined(__NEWLIB__) || __NEWLIB__ < 2 || \ __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 5 -#include -#include -#include +#include <__support/xlocale/__nop_locale_mgmt.h> +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> #endif #endif // _NEWLIB_VERSION diff --git a/libcxx/include/support/nuttx/xlocale.h b/libcxx/include/__support/nuttx/xlocale.h similarity index 70% rename from libcxx/include/support/nuttx/xlocale.h rename to libcxx/include/__support/nuttx/xlocale.h index b70d62005046c5492d4782aad6d896f9dfa9bfce..be738e3b64e488c83e34451152c1714ff49612e9 100644 --- a/libcxx/include/support/nuttx/xlocale.h +++ b/libcxx/include/__support/nuttx/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/nuttx/xlocale.h -------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ #define _LIBCPP_SUPPORT_NUTTX_XLOCALE_H #if defined(__NuttX__) -#include -#include +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> #endif // __NuttX__ #endif diff --git a/libcxx/include/support/openbsd/xlocale.h b/libcxx/include/__support/openbsd/xlocale.h similarity index 78% rename from libcxx/include/support/openbsd/xlocale.h rename to libcxx/include/__support/openbsd/xlocale.h index fbfaedd127c6c806fd5a5ae5bab7aa0d9b561964..1136fa327fac5549fa98e83d32ec9e7605e8f65a 100644 --- a/libcxx/include/support/openbsd/xlocale.h +++ b/libcxx/include/__support/openbsd/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/openbsd/xlocale.h -----------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,6 +14,6 @@ #include #include #include -#include +#include <__support/xlocale/__strtonum_fallback.h> #endif diff --git a/libcxx/include/support/solaris/floatingpoint.h b/libcxx/include/__support/solaris/floatingpoint.h similarity index 100% rename from libcxx/include/support/solaris/floatingpoint.h rename to libcxx/include/__support/solaris/floatingpoint.h diff --git a/libcxx/include/support/solaris/wchar.h b/libcxx/include/__support/solaris/wchar.h similarity index 100% rename from libcxx/include/support/solaris/wchar.h rename to libcxx/include/__support/solaris/wchar.h diff --git a/libcxx/include/support/solaris/xlocale.h b/libcxx/include/__support/solaris/xlocale.h similarity index 100% rename from libcxx/include/support/solaris/xlocale.h rename to libcxx/include/__support/solaris/xlocale.h diff --git a/libcxx/include/support/win32/limits_msvc_win32.h b/libcxx/include/__support/win32/limits_msvc_win32.h similarity index 96% rename from libcxx/include/support/win32/limits_msvc_win32.h rename to libcxx/include/__support/win32/limits_msvc_win32.h index 7bb835559a3b8f3b612d5cc4a4eae74efd036782..758d24647b1bfcffff62a8d992e09953e466da39 100644 --- a/libcxx/include/support/win32/limits_msvc_win32.h +++ b/libcxx/include/__support/win32/limits_msvc_win32.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------ support/win32/limits_msvc_win32.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/win32/locale_win32.h b/libcxx/include/__support/win32/locale_win32.h similarity index 99% rename from libcxx/include/support/win32/locale_win32.h rename to libcxx/include/__support/win32/locale_win32.h index 897c36be70c6215d8490bdc04a4a84845b191903..d32a7a8ad3042f765722a4df165e5e1c0bb767b5 100644 --- a/libcxx/include/support/win32/locale_win32.h +++ b/libcxx/include/__support/win32/locale_win32.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------- support/win32/locale_win32.h -------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/xlocale/__nop_locale_mgmt.h b/libcxx/include/__support/xlocale/__nop_locale_mgmt.h similarity index 94% rename from libcxx/include/support/xlocale/__nop_locale_mgmt.h rename to libcxx/include/__support/xlocale/__nop_locale_mgmt.h index f33d3894c3a9f57026b462ebbaf3a88a2afcfeba..57b18842ff45401180bc0647711eeb85ca0343b1 100644 --- a/libcxx/include/support/xlocale/__nop_locale_mgmt.h +++ b/libcxx/include/__support/xlocale/__nop_locale_mgmt.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------ support/xlocale/__nop_locale_mgmt.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/xlocale/__posix_l_fallback.h b/libcxx/include/__support/xlocale/__posix_l_fallback.h similarity index 98% rename from libcxx/include/support/xlocale/__posix_l_fallback.h rename to libcxx/include/__support/xlocale/__posix_l_fallback.h index f3df6c46fbab67aa6186cc8b1bf070941c04331f..00d69d19e8c8d6f1be6092d711ba786ea9c38507 100644 --- a/libcxx/include/support/xlocale/__posix_l_fallback.h +++ b/libcxx/include/__support/xlocale/__posix_l_fallback.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------- support/xlocale/__posix_l_fallback.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/xlocale/__strtonum_fallback.h b/libcxx/include/__support/xlocale/__strtonum_fallback.h similarity index 96% rename from libcxx/include/support/xlocale/__strtonum_fallback.h rename to libcxx/include/__support/xlocale/__strtonum_fallback.h index df38598056a6b6ac84b915df192599a9b4819650..1172a5d57236d55f3b0d4f5c24d0b2345fb1a14e 100644 --- a/libcxx/include/support/xlocale/__strtonum_fallback.h +++ b/libcxx/include/__support/xlocale/__strtonum_fallback.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------- support/xlocale/__strtonum_fallback.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index 473c9c3bbe49f09c535ec12471c92f6992696bfc..de572f3ff84d5f69057edebb20335a527b290761 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -17,7 +17,7 @@ #include #ifdef __MVS__ -# include +# include <__support/ibm/nanosleep.h> #endif #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER diff --git a/libcxx/include/bit b/libcxx/include/bit index fe360179c5ca04824f1390b1fb415240f12caee6..f8c37c3d6bbfe2b8e8d37f1595eee6704c03c07d 100644 --- a/libcxx/include/bit +++ b/libcxx/include/bit @@ -62,7 +62,7 @@ namespace std { #include <__debug> #if defined(__IBMCPP__) -#include "support/ibm/support.h" +#include "__support/ibm/support.h" #endif #if defined(_LIBCPP_COMPILER_MSVC) #include diff --git a/libcxx/include/fstream b/libcxx/include/fstream index d7d6b46c32d9039efa7a3dec9f574c6a7462c1a4..7b1bbfe16c013849678e9deccadc02deb89d5859 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -244,7 +244,7 @@ public: return open(__p.c_str(), __mode); } #endif - inline _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY basic_filebuf* __open(int __fd, ios_base::openmode __mode); #endif basic_filebuf* close(); @@ -574,7 +574,7 @@ basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) } template -inline _LIBCPP_INLINE_VISIBILITY +inline basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) { basic_filebuf<_CharT, _Traits>* __rt = nullptr; @@ -1326,6 +1326,7 @@ basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo } template +inline void basic_ifstream<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) { if (__sb_.__open(__fd, __mode | ios_base::in)) @@ -1539,6 +1540,7 @@ basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo } template +inline void basic_ofstream<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) { if (__sb_.__open(__fd, __mode | ios_base::out)) diff --git a/libcxx/include/limits b/libcxx/include/limits index 6d5d1e1aca75e574bd356821aecd99b7cd85aece..8f97cd10a8b1ffedcc36e84b46cacd6f7763c7ba 100644 --- a/libcxx/include/limits +++ b/libcxx/include/limits @@ -105,11 +105,11 @@ template<> class numeric_limits; #include #if defined(_LIBCPP_COMPILER_MSVC) -#include "support/win32/limits_msvc_win32.h" +#include "__support/win32/limits_msvc_win32.h" #endif // _LIBCPP_MSVCRT #if defined(__IBMCPP__) -#include "support/ibm/limits.h" +#include "__support/ibm/limits.h" #endif // __IBMCPP__ #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/memory b/libcxx/include/memory index a00916c8c03ffc446cc687b383e49e62810a0080..62235cf72b353503c4401bd1a03c569ef928ec9d 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -99,14 +99,14 @@ struct allocator_traits }; template <> -class allocator // deprecated in C++17, removed in C++20 +class allocator // removed in C++20 { public: - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; + typedef void* pointer; // deprecated in C++17 + typedef const void* const_pointer; // deprecated in C++17 + typedef void value_type; // deprecated in C++17 - template struct rebind {typedef allocator<_Up> other;}; + template struct rebind {typedef allocator<_Up> other;}; // deprecated in C++17 }; template @@ -786,34 +786,59 @@ to_address(const _Pointer& __p) _NOEXCEPT template class allocator; -#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) +#if _LIBCPP_STD_VER <= 17 template <> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator +class _LIBCPP_TEMPLATE_VIS allocator { public: - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; + _LIBCPP_DEPRECATED_IN_CXX17 typedef void* pointer; + _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; + _LIBCPP_DEPRECATED_IN_CXX17 typedef void value_type; - template struct rebind {typedef allocator<_Up> other;}; + template struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;}; }; template <> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator +class _LIBCPP_TEMPLATE_VIS allocator { public: - typedef const void* pointer; - typedef const void* const_pointer; - typedef const void value_type; + _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* pointer; + _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; + _LIBCPP_DEPRECATED_IN_CXX17 typedef const void value_type; - template struct rebind {typedef allocator<_Up> other;}; + template struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;}; }; #endif +// This class provides a non-trivial default constructor to the class that derives from it +// if the condition is satisfied. +// +// The second template parameter exists to allow giving a unique type to __non_trivial_if, +// which makes it possible to avoid breaking the ABI when making this a base class of an +// existing class. Without that, imagine we have classes D1 and D2, both of which used to +// have no base classes, but which now derive from __non_trivial_if. The layout of a class +// that inherits from both D1 and D2 will change because the two __non_trivial_if base +// classes are not allowed to share the same address. +// +// By making those __non_trivial_if base classes unique, we work around this problem and +// it is safe to start deriving from __non_trivial_if in existing classes. +template +struct __non_trivial_if { }; + +template +struct __non_trivial_if { + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR __non_trivial_if() _NOEXCEPT { } +}; + // allocator +// +// Note: For ABI compatibility between C++20 and previous standards, we make +// allocator trivial in C++20. template class _LIBCPP_TEMPLATE_VIS allocator + : private __non_trivial_if::value, allocator<_Tp> > { public: typedef size_t size_type; @@ -823,7 +848,7 @@ public: typedef true_type is_always_equal; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - allocator() _NOEXCEPT { } + allocator() _NOEXCEPT _LIBCPP_DEFAULT template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 @@ -895,6 +920,7 @@ public: template class _LIBCPP_TEMPLATE_VIS allocator + : private __non_trivial_if::value, allocator > { public: typedef size_t size_type; @@ -904,7 +930,7 @@ public: typedef true_type is_always_equal; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - allocator() _NOEXCEPT { } + allocator() _NOEXCEPT _LIBCPP_DEFAULT template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 @@ -2647,7 +2673,7 @@ private: _Alloc *__alloc = reinterpret_cast<_Alloc*>(__first); return __alloc; } - _Tp* __get_elem() _NOEXCEPT { + _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); _Tp *__elem = reinterpret_cast<_Tp*>(__second); @@ -2745,7 +2771,6 @@ public: typename enable_if < !is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible::pointer, element_type*>::value, __nat >::type = __nat()); @@ -2754,7 +2779,6 @@ public: typename enable_if < is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible::pointer, element_type*>::value, __nat >::type = __nat()); @@ -2795,7 +2819,6 @@ public: template typename enable_if < - !is_array<_Yp>::value && is_convertible::pointer, element_type*>::value, shared_ptr& >::type @@ -3157,7 +3180,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, typename enable_if < !is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible::pointer, element_type*>::value, __nat >::type) @@ -3170,7 +3192,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; + typedef __shared_ptr_pointer::pointer, _Dp, _AllocT > _CntrlBlk; __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } @@ -3183,7 +3205,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, typename enable_if < is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible::pointer, element_type*>::value, __nat >::type) @@ -3196,7 +3217,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, + typedef __shared_ptr_pointer::pointer, reference_wrapper::type>, _AllocT > _CntrlBlk; __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT()); @@ -3280,7 +3301,6 @@ template inline typename enable_if < - !is_array<_Yp>::value && is_convertible::pointer, typename shared_ptr<_Tp>::element_type*>::value, shared_ptr<_Tp>& diff --git a/libcxx/include/version b/libcxx/include/version index 813bc1ab9e6adb57c039ec37bbaa7540b1efef3b..c021db8bddd775c1f23ca8ac5d591f6dad77d6d0 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -184,7 +184,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_quoted_string_io 201304L # define __cpp_lib_result_of_sfinae 201210L # define __cpp_lib_robust_nonmodifying_seq_ops 201304L -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # define __cpp_lib_shared_timed_mutex 201402L # endif # define __cpp_lib_string_udls 201304L @@ -213,7 +213,9 @@ __cpp_lib_void_t 201411L # define __cpp_lib_clamp 201603L # define __cpp_lib_enable_shared_from_this 201603L // # define __cpp_lib_execution 201603L -# define __cpp_lib_filesystem 201703L +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# define __cpp_lib_filesystem 201703L +# endif # define __cpp_lib_gcd_lcm 201606L // # define __cpp_lib_hardware_interference_size 201703L # if defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS) @@ -241,7 +243,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_raw_memory_algorithms 201606L # define __cpp_lib_sample 201603L # define __cpp_lib_scoped_lock 201703L -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # define __cpp_lib_shared_mutex 201505L # endif # define __cpp_lib_shared_ptr_arrays 201611L @@ -279,10 +281,10 @@ __cpp_lib_void_t 201411L # if !defined(_LIBCPP_HAS_NO_THREADS) // # define __cpp_lib_atomic_value_initialization 201911L # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) # define __cpp_lib_atomic_wait 201907L # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) # define __cpp_lib_barrier 201907L # endif // # define __cpp_lib_bind_front 201907L @@ -326,7 +328,7 @@ __cpp_lib_void_t 201411L # if !defined(_LIBCPP_HAS_NO_THREADS) // # define __cpp_lib_jthread 201911L # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) # define __cpp_lib_latch 201907L # endif # define __cpp_lib_list_remove_return_type 201806L @@ -336,7 +338,7 @@ __cpp_lib_void_t 201411L // # define __cpp_lib_polymorphic_allocator 201902L // # define __cpp_lib_ranges 201811L # define __cpp_lib_remove_cvref 201711L -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # define __cpp_lib_semaphore 201907L # endif # define __cpp_lib_shift 201806L diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index c482068fa99ae59082627d0cca6e0c73b8ebd595..9965104cb5b23a2b472787722d14d544779a1e2e 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -107,7 +107,7 @@ endif() if (LIBCXX_CONFIGURE_IDE) file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*) if(WIN32) - file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/support/win32/*.h) + file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/__support/win32/*.h) list(APPEND LIBCXX_HEADERS ${LIBCXX_WIN32_HEADERS}) endif() # Force them all into the headers dir on MSVC, otherwise they end up at diff --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp index 6b73ed771cd1b15ddaab106332f1a8db150befd6..9ae1fb5199bf1fb8542e060b466842ad27fcc04e 100644 --- a/libcxx/src/atomic.cpp +++ b/libcxx/src/atomic.cpp @@ -19,6 +19,12 @@ #include #include +// libc++ uses SYS_futex as a universal syscall name. However, on 32 bit architectures +// with a 64 bit time_t, we need to specify SYS_futex_time64. +#if !defined(SYS_futex) && defined(SYS_futex_time64) +# define SYS_futex SYS_futex_time64 +#endif + #else // <- Add other operating systems here // Baseline needs no new headers diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index f109389f68f31f66b85b7174b770745b5c9784ce..a0209d0ce8cf4d320974e58d9fb809c8003fe1fb 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -29,7 +29,7 @@ #include "cwctype" #include "__sso_allocator" #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) -#include "support/win32/locale_win32.h" +#include "__support/win32/locale_win32.h" #elif !defined(__BIONIC__) && !defined(__NuttX__) #include #endif diff --git a/libcxx/src/support/solaris/xlocale.cpp b/libcxx/src/support/solaris/xlocale.cpp index d68a39f4dfe50031584d1fc0e835069280eb9ea3..d25adcd21d307dd88edbf1a7719e7425c1f52f45 100644 --- a/libcxx/src/support/solaris/xlocale.cpp +++ b/libcxx/src/support/solaris/xlocale.cpp @@ -8,7 +8,7 @@ #ifdef __sun__ -#include "support/solaris/xlocale.h" +#include "__support/solaris/xlocale.h" #include #include #include diff --git a/libcxx/src/support/win32/locale_win32.cpp b/libcxx/src/support/win32/locale_win32.cpp index b7062db352adcaea69a25f9fde2d6539627e8794..e7c6005fc1a361d002e5e49e6de474abfd5086a9 100644 --- a/libcxx/src/support/win32/locale_win32.cpp +++ b/libcxx/src/support/win32/locale_win32.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/win32/locale_win32.cpp ------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/src/support/win32/support.cpp b/libcxx/src/support/win32/support.cpp index d156e02e3e8498e716eb76b2f028e7455fb1ec45..52453f5479266aa2ffc487e650a183b8684bc5aa 100644 --- a/libcxx/src/support/win32/support.cpp +++ b/libcxx/src/support/win32/support.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -//===----------------------- support/win32/support.h ----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/src/support/win32/thread_win32.cpp b/libcxx/src/support/win32/thread_win32.cpp index 83e7e9f6ce5bf4d9063a4c8aca6bded2718e4466..35c4c871457dec633c1e7a56eb3b3f32be6e6526 100644 --- a/libcxx/src/support/win32/thread_win32.cpp +++ b/libcxx/src/support/win32/thread_win32.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/win32/thread_win32.cpp ------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/test/libcxx/debug/extern-templates.sh.cpp b/libcxx/test/libcxx/debug/extern-templates.sh.cpp index d5039d4f30296b592e058bf7145ed146752a2ebf..0e19895ba8f0a390484c624c607bb3fbb11a88a3 100644 --- a/libcxx/test/libcxx/debug/extern-templates.sh.cpp +++ b/libcxx/test/libcxx/debug/extern-templates.sh.cpp @@ -15,7 +15,7 @@ // UNSUPPORTED: libcpp-has-no-localization // RUN: %{cxx} %{flags} %{compile_flags} %s %{link_flags} -fPIC -DTU1 -D_LIBCPP_DEBUG=1 -fvisibility=hidden -shared -o %t.lib -// RUN: %{cxx} %{flags} %{compile_flags} %s %t.lib %{link_flags} -fPIC -DTU2 -D_LIBCPP_DEBUG=1 -fvisibility=hidden -o %t.exe +// RUN: cd %T && %{cxx} %{flags} %{compile_flags} %s ./%basename_t.tmp.lib %{link_flags} -fPIC -DTU2 -D_LIBCPP_DEBUG=1 -fvisibility=hidden -o %t.exe // RUN: %{exec} %t.exe #include diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp index bfff214127ba66101d8b419882327db9cb743f12..a6134b04a8f555ac254179bfcc915334da28916b 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp @@ -33,18 +33,19 @@ #include #include -#include "test_macros.h" - -int main(int, char**) -{ - static_assert((std::is_same::size_type, std::size_t>::value), ""); - static_assert((std::is_same::difference_type, std::ptrdiff_t>::value), ""); - static_assert((std::is_same::pointer, char*>::value), ""); - static_assert((std::is_same::const_pointer, const char*>::value), ""); - static_assert((std::is_same::reference, char&>::value), ""); - static_assert((std::is_same::const_reference, const char&>::value), ""); - static_assert((std::is_same::rebind::other, +template +void test() { + static_assert((std::is_same::size_type, std::size_t>::value), ""); + static_assert((std::is_same::difference_type, std::ptrdiff_t>::value), ""); + static_assert((std::is_same::pointer, T*>::value), ""); + static_assert((std::is_same::const_pointer, const T*>::value), ""); + static_assert((std::is_same::reference, T&>::value), ""); + static_assert((std::is_same::const_reference, const T&>::value), ""); + static_assert((std::is_same::template rebind::other, std::allocator >::value), ""); +} +int main(int, char**) { + test(); return 0; } diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py index af473c48ea9ab0daf532f9df62664e066af4d69a..4621e638834349c54ffbc62e78b1ed3e3373f6a0 100644 --- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py +++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py @@ -37,6 +37,23 @@ class CheckResult(gdb.Command): compare_frame = gdb.newest_frame().older() testcase_frame = compare_frame.older() test_loc = testcase_frame.find_sal() + + expectation_val = compare_frame.read_var("expectation") + check_literal = expectation_val.string(encoding="utf-8") + + # Heuristic to determine if libc++ itself has debug + # info. If it doesn't, then anything normally homed there + # won't be found, and the printer will error. We don't + # want to fail the test in this case--the printer itself + # is probably fine, or at least we can't tell. + if check_literal.startswith("std::shared_ptr"): + shared_ptr = compare_frame.read_var("value") + if not "__shared_owners_" in shared_ptr.type.fields(): + print("IGNORED (no debug info in libc++): " + + test_loc.symtab.filename + ":" + + str(test_loc.line)) + return + # Use interactive commands in the correct context to get the pretty # printed version @@ -45,11 +62,10 @@ class CheckResult(gdb.Command): # Ignore the convenience variable name and newline value = value_str[value_str.find("= ") + 2:-1] gdb.newest_frame().select() - expectation_val = compare_frame.read_var("expectation") check_literal = expectation_val.string(encoding="utf-8") if "PrettyPrintToRegex" in compare_frame.name(): - test_fails = not re.match(check_literal, value) + test_fails = not re.search(check_literal, value) else: test_fails = value != check_literal diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp index fed6a161848393a856bd58fed957ca04931fb4e3..2d8e9620089a40d260f49e985daa9d2338e42d79 100644 --- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp +++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp @@ -427,9 +427,9 @@ void multiset_test() { void vector_test() { std::vector test0 = {true, false}; - ComparePrettyPrintToChars(test0, + ComparePrettyPrintToRegex(test0, "std::vector of " - "length 2, capacity 64 = {1, 0}"); + "length 2, capacity (32|64) = {1, 0}"); for (int i = 0; i < 31; ++i) { test0.push_back(true); test0.push_back(false); @@ -444,9 +444,9 @@ void vector_test() { ComparePrettyPrintToRegex( test0, "std::vector of length 65, " - "capacity 128 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, " - "1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, " - "1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}"); + "capacity (96|128) = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, " + "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, " + "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}"); std::vector test1; ComparePrettyPrintToChars(test1, "std::vector of length 0, capacity 0"); @@ -489,8 +489,9 @@ void map_iterator_test() { auto not_found = one_two_three.find(7); MarkAsLive(not_found); - CompareExpressionPrettyPrintToRegex("not_found", - R"(std::__map_iterator = {\[0x[a-f0-9]+\] = end\(\)})"); + // Because the end_node is not easily detected, just be sure it doesn't crash. + CompareExpressionPrettyPrintToRegex( + "not_found", R"(std::__map_iterator ( = {\[0x[a-f0-9]+\] = .*}|))"); } void unordered_set_test() { @@ -607,25 +608,27 @@ void shared_ptr_test() { // due to which there is one more count for the pointer. Hence, all the // following tests are testing with expected count plus 1. std::shared_ptr test0 = std::make_shared(5); + // The python regular expression matcher treats newlines as significant, so + // these regular expressions should be on one line. ComparePrettyPrintToRegex( test0, - R"(std::shared_ptr count 2, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [2\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); std::shared_ptr test1(test0); ComparePrettyPrintToRegex( test1, - R"(std::shared_ptr count 3, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); { std::weak_ptr test2 = test1; ComparePrettyPrintToRegex( test0, - R"(std::shared_ptr count 3, weak 1 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [3\?], weak [1\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); } ComparePrettyPrintToRegex( test0, - R"(std::shared_ptr count 3, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); std::shared_ptr test3; ComparePrettyPrintToChars(test3, "std::shared_ptr is nullptr"); diff --git a/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp b/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9d67c065de85ea48d1e1c4dc3398089b6a250fb --- /dev/null +++ b/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure that std::allocator is trivial. This was the case before C++20 +// with the std::allocator explicit specialization, and this test makes sure +// that we maintain that property across all standards. +// +// This is important since triviality has implications on how the type is passed +// as a function argument in the ABI. + +#include +#include + +typedef std::allocator A1; +typedef std::allocator A2; +struct A3 : std::allocator { }; +struct A4 : std::allocator { }; + +static_assert(std::is_trivially_default_constructible::value, ""); +static_assert(std::is_trivial::value, ""); + +static_assert(std::is_trivially_default_constructible::value, ""); +static_assert(std::is_trivial::value, ""); + +static_assert(std::is_trivially_default_constructible::value, ""); +static_assert(std::is_trivial::value, ""); + +static_assert(std::is_trivially_default_constructible::value, ""); +static_assert(std::is_trivial::value, ""); diff --git a/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp b/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp index 73fe18becc3a96cf7aa539e50b5c110bb7ccc269..5cda71371fa612d886db244ca197d0571460743c 100644 --- a/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp +++ b/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp @@ -46,7 +46,11 @@ int main(int, char**) { // // With trivial_abi, local_addr is the address of a local variable in // make_val, and hence different from &ret. +#if !defined(__i386__) + // On X86, structs are never returned in registers. + // Thus, unique_ptr will be passed indirectly even if it is trivial. assert((void*)&ret != local_addr); +#endif return 0; } diff --git a/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp b/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp index e69c94506f2aff0e19b18cbbec3d8576e0739007..9b4e95e249e2337f06694b683e13d0ff60eb922d 100644 --- a/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp +++ b/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp @@ -49,9 +49,10 @@ int main(int, char**) { // // With trivial_abi, local_addr is the address of a local variable in // make_val, and hence different from &ret. -#ifndef __arm__ +#if !defined(__i386__) && !defined(__arm__) + // On X86, structs are never returned in registers. // On ARM32, structs larger than 4 bytes cannot be returned in registers. - // Thus, weak_ptr will be passed indrectly even if it is trivial. + // Thus, weak_ptr will be passed indirectly even if it is trivial. assert((void*)&ret != local_addr); #endif return 0; diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/expected.pass.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/expected.pass.cpp index 2bd297660c4ed1c7ce22382b080ddf1127f2120e..5b307508abeb5a0550051ceeda11f9bd3fe1e60f 100644 --- a/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/expected.pass.cpp +++ b/libcxx/test/std/experimental/language.support/support.coroutines/end.to.end/expected.pass.cpp @@ -35,7 +35,7 @@ struct expected { struct promise_type { std::shared_ptr data; - std::shared_ptr get_return_object() { data = std::make_shared(); return data; } + expected get_return_object() { data = std::make_shared(); return {data}; } suspend_never initial_suspend() { return {}; } suspend_never final_suspend() noexcept { return {}; } void return_value(T v) { data->val = v; data->error = {}; } diff --git a/libcxx/test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp deleted file mode 100644 index 6b7052b2403d3ea4b68474acfe1564a23d13df83..0000000000000000000000000000000000000000 --- a/libcxx/test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// #define __cpp_lib_filesystem 201703L - -#include -#include "test_macros.h" - -#if TEST_STD_VER >= 17 -#ifndef __cpp_lib_filesystem -#error Filesystem feature test macro is not defined (__cpp_lib_filesystem) -#elif __cpp_lib_filesystem != 201703L -#error Filesystem feature test macro has an incorrect value (__cpp_lib_filesystem) -#endif -#else // TEST_STD_VER < 17 -#ifdef __cpp_lib_filesystem -#error Filesystem feature test macro should not be defined before C++17 -#endif -#endif - -int main(int, char**) { - return 0; -} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp index b964e0c6921e28197cc3c466fcffd8d2927a1e29..c8a837115adef637ff0f57323a8d08b0aaee0221 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp @@ -248,7 +248,7 @@ # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) # ifndef __cpp_lib_atomic_wait # error "__cpp_lib_atomic_wait should be defined in c++20" # endif @@ -257,7 +257,7 @@ # endif # else # ifdef __cpp_lib_atomic_wait -# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) is not defined!" # endif # endif @@ -367,7 +367,7 @@ # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) # ifndef __cpp_lib_atomic_wait # error "__cpp_lib_atomic_wait should be defined in c++2b" # endif @@ -376,7 +376,7 @@ # endif # else # ifdef __cpp_lib_atomic_wait -# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) is not defined!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp index b193095403e9afc7785a0f8bdecdfdabc52b5b23..80f7d9ca24b41f4690c97c20f1a025f25ccb0ad5 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp @@ -44,7 +44,7 @@ #elif TEST_STD_VER == 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) # ifndef __cpp_lib_barrier # error "__cpp_lib_barrier should be defined in c++20" # endif @@ -53,13 +53,13 @@ # endif # else # ifdef __cpp_lib_barrier -# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) is not defined!" # endif # endif #elif TEST_STD_VER > 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) # ifndef __cpp_lib_barrier # error "__cpp_lib_barrier should be defined in c++2b" # endif @@ -68,7 +68,7 @@ # endif # else # ifdef __cpp_lib_barrier -# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) is not defined!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp index 6e47bdf3b5fefb2eac94e7955aa24e1a40a27740..c361569cb1d6d4ac69ca11fef2df14832a3de924 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp @@ -51,11 +51,17 @@ # error "__cpp_lib_char8_t should not be defined before c++20" # endif -# ifndef __cpp_lib_filesystem -# error "__cpp_lib_filesystem should be defined in c++17" -# endif -# if __cpp_lib_filesystem != 201703L -# error "__cpp_lib_filesystem should have the value 201703L in c++17" +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# ifndef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should be defined in c++17" +# endif +# if __cpp_lib_filesystem != 201703L +# error "__cpp_lib_filesystem should have the value 201703L in c++17" +# endif +# else +# ifdef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should not be defined when !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) is not defined!" +# endif # endif #elif TEST_STD_VER == 20 @@ -73,11 +79,17 @@ # endif # endif -# ifndef __cpp_lib_filesystem -# error "__cpp_lib_filesystem should be defined in c++20" -# endif -# if __cpp_lib_filesystem != 201703L -# error "__cpp_lib_filesystem should have the value 201703L in c++20" +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# ifndef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should be defined in c++20" +# endif +# if __cpp_lib_filesystem != 201703L +# error "__cpp_lib_filesystem should have the value 201703L in c++20" +# endif +# else +# ifdef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should not be defined when !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) is not defined!" +# endif # endif #elif TEST_STD_VER > 20 @@ -95,11 +107,17 @@ # endif # endif -# ifndef __cpp_lib_filesystem -# error "__cpp_lib_filesystem should be defined in c++2b" -# endif -# if __cpp_lib_filesystem != 201703L -# error "__cpp_lib_filesystem should have the value 201703L in c++2b" +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# ifndef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should be defined in c++2b" +# endif +# if __cpp_lib_filesystem != 201703L +# error "__cpp_lib_filesystem should have the value 201703L in c++2b" +# endif +# else +# ifdef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should not be defined when !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) is not defined!" +# endif # endif #endif // TEST_STD_VER > 20 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp index 29e8fd617bbfe57930f7d8fad9127550c5f92484..56db3ba66b450c0d948f1be469c4fd57f2f72a73 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp @@ -44,7 +44,7 @@ #elif TEST_STD_VER == 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) # ifndef __cpp_lib_latch # error "__cpp_lib_latch should be defined in c++20" # endif @@ -53,13 +53,13 @@ # endif # else # ifdef __cpp_lib_latch -# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) is not defined!" # endif # endif #elif TEST_STD_VER > 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) # ifndef __cpp_lib_latch # error "__cpp_lib_latch should be defined in c++2b" # endif @@ -68,7 +68,7 @@ # endif # else # ifdef __cpp_lib_latch -# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) is not defined!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp index febeb6f6c61557bd663a4b6a3dea936583e275fd..79e31aa06a3f4c286dec16490714d9978c441866 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp @@ -44,7 +44,7 @@ #elif TEST_STD_VER == 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # ifndef __cpp_lib_semaphore # error "__cpp_lib_semaphore should be defined in c++20" # endif @@ -53,13 +53,13 @@ # endif # else # ifdef __cpp_lib_semaphore -# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) is not defined!" # endif # endif #elif TEST_STD_VER > 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # ifndef __cpp_lib_semaphore # error "__cpp_lib_semaphore should be defined in c++2b" # endif @@ -68,7 +68,7 @@ # endif # else # ifdef __cpp_lib_semaphore -# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) is not defined!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp index 953fd0a37790a880177a47b11bd1508d7cceb315..d26a453f83c3d2a9bf9bad9c6e60aeb527727cec 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp @@ -41,7 +41,7 @@ # error "__cpp_lib_shared_mutex should not be defined before c++17" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++14" # endif @@ -50,13 +50,13 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif #elif TEST_STD_VER == 17 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # ifndef __cpp_lib_shared_mutex # error "__cpp_lib_shared_mutex should be defined in c++17" # endif @@ -65,11 +65,11 @@ # endif # else # ifdef __cpp_lib_shared_mutex -# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++17" # endif @@ -78,13 +78,13 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif #elif TEST_STD_VER == 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # ifndef __cpp_lib_shared_mutex # error "__cpp_lib_shared_mutex should be defined in c++20" # endif @@ -93,11 +93,11 @@ # endif # else # ifdef __cpp_lib_shared_mutex -# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++20" # endif @@ -106,13 +106,13 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif #elif TEST_STD_VER > 20 -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # ifndef __cpp_lib_shared_mutex # error "__cpp_lib_shared_mutex should be defined in c++2b" # endif @@ -121,11 +121,11 @@ # endif # else # ifdef __cpp_lib_shared_mutex -# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++2b" # endif @@ -134,7 +134,7 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp index 9e96e2e116e018f876ccaf98092db8d21fb8333e..1de99be54e30907b60cdc580fe6c305446fe6e75 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -1133,7 +1133,7 @@ # error "__cpp_lib_shared_ptr_weak_type should not be defined before c++17" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++14" # endif @@ -1142,7 +1142,7 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif @@ -1534,11 +1534,17 @@ # endif # endif -# ifndef __cpp_lib_filesystem -# error "__cpp_lib_filesystem should be defined in c++17" -# endif -# if __cpp_lib_filesystem != 201703L -# error "__cpp_lib_filesystem should have the value 201703L in c++17" +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# ifndef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should be defined in c++17" +# endif +# if __cpp_lib_filesystem != 201703L +# error "__cpp_lib_filesystem should have the value 201703L in c++17" +# endif +# else +# ifdef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should not be defined when !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) is not defined!" +# endif # endif # ifndef __cpp_lib_gcd_lcm @@ -1883,7 +1889,7 @@ # error "__cpp_lib_semaphore should not be defined before c++20" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # ifndef __cpp_lib_shared_mutex # error "__cpp_lib_shared_mutex should be defined in c++17" # endif @@ -1892,7 +1898,7 @@ # endif # else # ifdef __cpp_lib_shared_mutex -# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) is not defined!" # endif # endif @@ -1910,7 +1916,7 @@ # error "__cpp_lib_shared_ptr_weak_type should have the value 201606L in c++17" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++17" # endif @@ -1919,7 +1925,7 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif @@ -2223,7 +2229,7 @@ # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) # ifndef __cpp_lib_atomic_wait # error "__cpp_lib_atomic_wait should be defined in c++20" # endif @@ -2232,11 +2238,11 @@ # endif # else # ifdef __cpp_lib_atomic_wait -# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) # ifndef __cpp_lib_barrier # error "__cpp_lib_barrier should be defined in c++20" # endif @@ -2245,7 +2251,7 @@ # endif # else # ifdef __cpp_lib_barrier -# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) is not defined!" # endif # endif @@ -2575,11 +2581,17 @@ # endif # endif -# ifndef __cpp_lib_filesystem -# error "__cpp_lib_filesystem should be defined in c++20" -# endif -# if __cpp_lib_filesystem != 201703L -# error "__cpp_lib_filesystem should have the value 201703L in c++20" +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# ifndef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should be defined in c++20" +# endif +# if __cpp_lib_filesystem != 201703L +# error "__cpp_lib_filesystem should have the value 201703L in c++20" +# endif +# else +# ifdef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should not be defined when !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) is not defined!" +# endif # endif # ifndef __cpp_lib_gcd_lcm @@ -2795,7 +2807,7 @@ # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) # ifndef __cpp_lib_latch # error "__cpp_lib_latch should be defined in c++20" # endif @@ -2804,7 +2816,7 @@ # endif # else # ifdef __cpp_lib_latch -# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) is not defined!" # endif # endif @@ -3019,7 +3031,7 @@ # error "__cpp_lib_scoped_lock should have the value 201703L in c++20" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # ifndef __cpp_lib_semaphore # error "__cpp_lib_semaphore should be defined in c++20" # endif @@ -3028,11 +3040,11 @@ # endif # else # ifdef __cpp_lib_semaphore -# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # ifndef __cpp_lib_shared_mutex # error "__cpp_lib_shared_mutex should be defined in c++20" # endif @@ -3041,7 +3053,7 @@ # endif # else # ifdef __cpp_lib_shared_mutex -# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) is not defined!" # endif # endif @@ -3059,7 +3071,7 @@ # error "__cpp_lib_shared_ptr_weak_type should have the value 201606L in c++20" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++20" # endif @@ -3068,7 +3080,7 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif @@ -3429,7 +3441,7 @@ # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) # ifndef __cpp_lib_atomic_wait # error "__cpp_lib_atomic_wait should be defined in c++2b" # endif @@ -3438,11 +3450,11 @@ # endif # else # ifdef __cpp_lib_atomic_wait -# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) # ifndef __cpp_lib_barrier # error "__cpp_lib_barrier should be defined in c++2b" # endif @@ -3451,7 +3463,7 @@ # endif # else # ifdef __cpp_lib_barrier -# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_barrier should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) is not defined!" # endif # endif @@ -3781,11 +3793,17 @@ # endif # endif -# ifndef __cpp_lib_filesystem -# error "__cpp_lib_filesystem should be defined in c++2b" -# endif -# if __cpp_lib_filesystem != 201703L -# error "__cpp_lib_filesystem should have the value 201703L in c++2b" +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# ifndef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should be defined in c++2b" +# endif +# if __cpp_lib_filesystem != 201703L +# error "__cpp_lib_filesystem should have the value 201703L in c++2b" +# endif +# else +# ifdef __cpp_lib_filesystem +# error "__cpp_lib_filesystem should not be defined when !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) is not defined!" +# endif # endif # ifndef __cpp_lib_gcd_lcm @@ -4004,7 +4022,7 @@ # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) # ifndef __cpp_lib_latch # error "__cpp_lib_latch should be defined in c++2b" # endif @@ -4013,7 +4031,7 @@ # endif # else # ifdef __cpp_lib_latch -# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_latch should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) is not defined!" # endif # endif @@ -4228,7 +4246,7 @@ # error "__cpp_lib_scoped_lock should have the value 201703L in c++2b" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # ifndef __cpp_lib_semaphore # error "__cpp_lib_semaphore should be defined in c++2b" # endif @@ -4237,11 +4255,11 @@ # endif # else # ifdef __cpp_lib_semaphore -# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_semaphore should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) is not defined!" # endif # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) # ifndef __cpp_lib_shared_mutex # error "__cpp_lib_shared_mutex should be defined in c++2b" # endif @@ -4250,7 +4268,7 @@ # endif # else # ifdef __cpp_lib_shared_mutex -# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) is not defined!" # endif # endif @@ -4268,7 +4286,7 @@ # error "__cpp_lib_shared_ptr_weak_type should have the value 201606L in c++2b" # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) # ifndef __cpp_lib_shared_timed_mutex # error "__cpp_lib_shared_timed_mutex should be defined in c++2b" # endif @@ -4277,7 +4295,7 @@ # endif # else # ifdef __cpp_lib_shared_timed_mutex -# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" +# error "__cpp_lib_shared_timed_mutex should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) is not defined!" # endif # endif diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/PR50299.compile.pass.cpp similarity index 45% rename from libcxx/test/std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp rename to libcxx/test/std/utilities/memory/default.allocator/PR50299.compile.pass.cpp index cd98e6364b7ed28cd89946e9404938c571b6bfec..245d3d9d320fa49eb93ce9b1ebf3222d1e1012dd 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/PR50299.compile.pass.cpp @@ -8,17 +8,13 @@ // -// Check that allocator is deprecated in C++17. - -// REQUIRES: c++17 +// Make sure we can use std::allocator in all Standard modes. While the +// explicit specialization for std::allocator was deprecated, using that +// specialization was neither deprecated nor removed (in C++20 it should simply +// start using the primary template). +// +// See https://llvm.org/PR50299. #include -#include "test_macros.h" -int main(int, char**) -{ - typedef std::allocator::pointer AP; // expected-warning {{'allocator' is deprecated}} - typedef std::allocator::const_pointer ACP; // expected-warning {{'allocator' is deprecated}} - typedef std::allocator::rebind::other ARO; // expected-warning {{'allocator' is deprecated}} - return 0; -} +std::allocator a; diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp index 28bfe41680b6e08ad07885e305a06676459aa256..6e6ff1f2d1344b287f1f3358bd502420e375976a 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp @@ -7,15 +7,14 @@ //===----------------------------------------------------------------------===// // -// UNSUPPORTED: c++03, c++11, c++14, c++17 // // template // class allocator // { // public: // All of these are constexpr after C++17 -// constexpr allocator() noexcept; -// constexpr allocator(const allocator&) noexcept; -// template constexpr allocator(const allocator&) noexcept; +// allocator() noexcept; +// allocator(const allocator&) noexcept; +// template allocator(const allocator&) noexcept; // ... // }; @@ -24,28 +23,27 @@ #include "test_macros.h" +template +TEST_CONSTEXPR_CXX20 bool test() { + typedef std::allocator A1; + typedef std::allocator A2; -int main(int, char**) -{ - { - typedef std::allocator AC; - typedef std::allocator AL; + A1 a1; + A1 a1_copy = a1; (void)a1_copy; + A2 a2 = a1; (void)a2; - constexpr AC a1; - constexpr AC a2{a1}; - constexpr AL a3{a2}; - (void) a3; - } - { - typedef std::allocator AC; - typedef std::allocator AL; - - constexpr AC a1; - constexpr AC a2{a1}; - constexpr AL a3{a2}; - (void) a3; - } + return true; +} +int main(int, char**) { + test(); + test(); + test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp index 7ae87dd453538968c0ca2ed73874e3307fd37d1f..a095ca102491e08d97c22d4072c43e8ecade7354 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp @@ -13,7 +13,6 @@ #include - template constexpr bool test() { std::allocator alloc; @@ -26,11 +25,13 @@ constexpr bool test() { int main(int, char**) { test(); + test(); #ifdef _LIBCPP_VERSION // extension test(); #endif // _LIBCPP_VERSION static_assert(test()); + static_assert(test()); #ifdef _LIBCPP_VERSION // extension static_assert(test()); #endif // _LIBCPP_VERSION diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp index 27e91a650e69f5d1d98910fee0f21dc5a7ab274c..777e5dfc44f59a93c94203a69a5f16df703768fb 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp @@ -11,9 +11,9 @@ #include #include -// #include - #include "test_macros.h" + +// // // template // struct allocator_traits diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp index f09651a81eeeca26395c9735442953dd0b85aff1..88af53a4eeaab3c9e12d5decbfc7afb12ef7a747 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp @@ -30,20 +30,27 @@ // UNSUPPORTED: clang-6 #include -#include "test_macros.h" -int main(int, char**) -{ - typedef std::allocator::pointer AP; // expected-warning {{'pointer' is deprecated}} - typedef std::allocator::const_pointer ACP; // expected-warning {{'const_pointer' is deprecated}} - typedef std::allocator::reference AR; // expected-warning {{'reference' is deprecated}} - typedef std::allocator::const_reference ACR; // expected-warning {{'const_reference' is deprecated}} - typedef std::allocator::rebind::other ARO; // expected-warning {{'rebind' is deprecated}} - - typedef std::allocator::pointer AP2; // expected-warning {{'pointer' is deprecated}} - typedef std::allocator::const_pointer ACP2; // expected-warning {{'const_pointer' is deprecated}} - typedef std::allocator::reference AR2; // expected-warning {{'reference' is deprecated}} - typedef std::allocator::const_reference ACR2; // expected-warning {{'const_reference' is deprecated}} - typedef std::allocator::rebind::other ARO2; // expected-warning {{'rebind' is deprecated}} +int main(int, char**) { + { + typedef std::allocator::pointer Pointer; // expected-warning {{'pointer' is deprecated}} + typedef std::allocator::const_pointer ConstPointer; // expected-warning {{'const_pointer' is deprecated}} + typedef std::allocator::reference Reference; // expected-warning {{'reference' is deprecated}} + typedef std::allocator::const_reference ConstReference; // expected-warning {{'const_reference' is deprecated}} + typedef std::allocator::rebind::other Rebind; // expected-warning {{'rebind' is deprecated}} + } + { + typedef std::allocator::pointer Pointer; // expected-warning {{'pointer' is deprecated}} + typedef std::allocator::const_pointer ConstPointer; // expected-warning {{'const_pointer' is deprecated}} + typedef std::allocator::reference Reference; // expected-warning {{'reference' is deprecated}} + typedef std::allocator::const_reference ConstReference; // expected-warning {{'const_reference' is deprecated}} + typedef std::allocator::rebind::other Rebind; // expected-warning {{'rebind' is deprecated}} + } + { + typedef std::allocator::pointer Pointer; // expected-warning {{'pointer' is deprecated}} + typedef std::allocator::const_pointer ConstPointer; // expected-warning {{'const_pointer' is deprecated}} + // reference and const_reference are not provided by std::allocator + typedef std::allocator::rebind::other Rebind; // expected-warning {{'rebind' is deprecated}} + } return 0; } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp index 6a034935a30d4903d46fe78caf3691c462588685..74adc6943594dcb1d9e12fb68eb1efba0b91ad7f 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp @@ -18,47 +18,49 @@ // typedef ptrdiff_t difference_type; // typedef T value_type; // +// typedef T* pointer; // deprecated in C++17, removed in C++20 +// typedef T const* const_pointer; // deprecated in C++17, removed in C++20 +// typedef T& reference; // deprecated in C++17, removed in C++20 +// typedef T const& const_reference; // deprecated in C++17, removed in C++20 +// template< class U > struct rebind { typedef allocator other; }; // deprecated in C++17, removed in C++20 +// // typedef true_type propagate_on_container_move_assignment; // typedef true_type is_always_equal; // ... // }; +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS + #include #include #include #include "test_macros.h" -template -TEST_CONSTEXPR_CXX20 bool test() -{ - static_assert((std::is_same::size_type, std::size_t>::value), ""); - static_assert((std::is_same::difference_type, std::ptrdiff_t>::value), ""); - static_assert((std::is_same::value_type, T>::value), ""); - static_assert((std::is_same::propagate_on_container_move_assignment, std::true_type>::value), ""); - static_assert((std::is_same::is_always_equal, std::true_type>::value), ""); +struct U; - std::allocator a; - std::allocator a2 = a; - a2 = a; - std::allocator a3 = a2; - (void)a3; +template +void test() { + typedef std::allocator Alloc; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); - return true; +#if TEST_STD_VER <= 17 + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::other, std::allocator >::value), ""); +#endif } -int main(int, char**) -{ - test(); -#ifdef _LIBCPP_VERSION // extension - test(); -#endif // _LIBCPP_VERSION - -#if TEST_STD_VER > 17 - static_assert(test()); -#ifdef _LIBCPP_VERSION // extension - static_assert(test()); -#endif // _LIBCPP_VERSION +int main(int, char**) { + test(); +#ifdef _LIBCPP_VERSION + test(); // extension #endif return 0; } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp index 9805accda20afc0d5229582711ba8c43892a01b4..1d91a022867da6557afe3da63d9bcdae0123a0fb 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp @@ -31,16 +31,17 @@ template void check() { - typedef typename std::allocator::pointer AP; // expected-error 2 {{no type named 'pointer'}} - typedef typename std::allocator::const_pointer ACP; // expected-error 2 {{no type named 'const_pointer'}} - typedef typename std::allocator::reference AR; // expected-error 2 {{no type named 'reference'}} - typedef typename std::allocator::const_reference ACR; // expected-error 2 {{no type named 'const_reference'}} - typedef typename std::allocator::template rebind::other ARO; // expected-error 2 {{no member named 'rebind'}} + typedef typename std::allocator::pointer AP; // expected-error 3 {{no type named 'pointer'}} + typedef typename std::allocator::const_pointer ACP; // expected-error 3 {{no type named 'const_pointer'}} + typedef typename std::allocator::reference AR; // expected-error 3 {{no type named 'reference'}} + typedef typename std::allocator::const_reference ACR; // expected-error 3 {{no type named 'const_reference'}} + typedef typename std::allocator::template rebind::other ARO; // expected-error 3 {{no member named 'rebind'}} } int main(int, char**) { check(); check(); + check(); return 0; } diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_void.cxx2a.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.void.compile.pass.cpp similarity index 51% rename from libcxx/test/libcxx/depr/depr.default.allocator/allocator_void.cxx2a.pass.cpp rename to libcxx/test/std/utilities/memory/default.allocator/allocator_types.void.compile.pass.cpp index d03f90b506d552a625528aea1e051c9bc71659bb..d7b4a1b1bdf4da64d7f8680820371642e517c722 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_void.cxx2a.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.void.compile.pass.cpp @@ -6,10 +6,11 @@ // //===----------------------------------------------------------------------===// -// +// Check that the nested types of std::allocator are provided. +// After C++17, those are not provided in the primary template and the +// explicit specialization doesn't exist anymore, so this test is moot. -// Check that the following member types of allocator are provided -// regardless of the Standard when we request them from libc++. +// REQUIRES: c++03 || c++11 || c++14 || c++17 // template <> // class allocator @@ -22,24 +23,13 @@ // template struct rebind {typedef allocator<_Up> other;}; // }; -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS #include #include -#include "test_macros.h" - -int main(int, char**) -{ - static_assert((std::is_same::pointer, void*>::value), ""); - static_assert((std::is_same::const_pointer, const void*>::value), ""); - static_assert((std::is_same::value_type, void>::value), ""); - static_assert((std::is_same::rebind::other, - std::allocator >::value), ""); - std::allocator a; - std::allocator a2 = a; - a2 = a; - - return 0; -} +static_assert((std::is_same::pointer, void*>::value), ""); +static_assert((std::is_same::const_pointer, const void*>::value), ""); +static_assert((std::is_same::value_type, void>::value), ""); +static_assert((std::is_same::rebind::other, + std::allocator >::value), ""); diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp index 0096897ee07e654eaf808cd50709961da44e9a89..f9e1798d8a7a69f59e86f55512e8639b850a1921 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp @@ -41,6 +41,19 @@ struct A int A::count = 0; +template +struct StatefulArrayDeleter { + int state = 0; + + StatefulArrayDeleter(int val = 0) : state(val) {} + StatefulArrayDeleter(StatefulArrayDeleter const&) { assert(false); } + + void operator()(T* ptr) { + assert(state == 42); + delete []ptr; + } +}; + int main(int, char**) { { @@ -112,5 +125,82 @@ int main(int, char**) assert(B::count == 0); assert(A::count == 0); + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p; + p = std::move(ptr); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p; + p = std::move(ptr); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr ptr(new int[8]); + std::shared_ptr p; + p = std::move(ptr); + } + +#if TEST_STD_VER > 14 + { + StatefulArrayDeleter d; + std::unique_ptr&> u(new A[4], d); + std::shared_ptr p; + p = std::move(u); + d.state = 42; + assert(A::count == 4); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p; + p = std::move(ptr); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p; + p = std::move(ptr); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr ptr(new int[8]); + std::shared_ptr p; + p = std::move(ptr); + } +#endif // TEST_STD_VER >= 14 + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp index 398c64ee6d74a7c3620a061a8affcedae48f756b..ad88a3e8a7dfc0dd2867c5e6e2fc355d34dd8e07 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp @@ -10,7 +10,7 @@ // -// template explicit shared_ptr(unique_ptr&&r); +// template shared_ptr(unique_ptr&&r); #include #include @@ -69,6 +69,19 @@ struct StatefulDeleter { } }; +template +struct StatefulArrayDeleter { + int state = 0; + + StatefulArrayDeleter(int val = 0) : state(val) {} + StatefulArrayDeleter(StatefulArrayDeleter const&) { assert(false); } + + void operator()(T* ptr) { + assert(state == 42); + delete []ptr; + } +}; + int main(int, char**) { { @@ -135,5 +148,76 @@ int main(int, char**) std::shared_ptr s = std::move(u); } - return 0; + assert(A::count == 0); + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p(std::move(ptr)); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p(std::move(ptr)); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr ptr(new int[8]); + std::shared_ptr p(std::move(ptr)); + } + +#if TEST_STD_VER > 14 + { + StatefulArrayDeleter d; + std::unique_ptr&> u(new A[4], d); + std::shared_ptr p(std::move(u)); + d.state = 42; + assert(A::count == 4); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p(std::move(ptr)); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr p(std::move(ptr)); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr ptr(new int[8]); + std::shared_ptr p(std::move(ptr)); + } +#endif // TEST_STD_VER >= 14 + + return 0; } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp index db0958ca6de18c655259849d47e427d8d7971557..4951ae22d406910a803f030438a54b2a45995e1f 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp @@ -13,7 +13,7 @@ // GCC's implementation of class template deduction is still immature and runs // into issues with libc++. However GCC accepts this code when compiling // against libstdc++. -// XFAIL: gcc-5, gcc-6, gcc-7 +// XFAIL: gcc-5, gcc-6, gcc-7, gcc-8, gcc-9, gcc-10, gcc-11 // diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot index 1fb09f3a91aa0dc63d1f5b1f04174c2eebea2771..d3880816779fd6343e87211b67feb9761924d422 100755 --- a/libcxx/utils/ci/run-buildbot +++ b/libcxx/utils/ci/run-buildbot @@ -168,8 +168,8 @@ generic-32bit) check-cxx-cxxabi ;; generic-gcc) - export CC=gcc - export CXX=g++ + export CC=gcc-10 + export CXX=g++-10 clean # FIXME: Re-enable experimental testing on GCC. GCC cares about the order # in which we link -lc++experimental, which causes issues. diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py index 0ee446f46c51f7f03c33a99c2029385ae949db91..9d9a96a3e36f72bf87734e9b9cb067c39ed44aa2 100644 --- a/libcxx/utils/gdb/libcxx/printers.py +++ b/libcxx/utils/gdb/libcxx/printers.py @@ -13,6 +13,7 @@ and when it is undefined. from __future__ import print_function +import math import re import gdb @@ -141,7 +142,7 @@ class StdTuplePrinter(object): def __next__(self): # child_iter raises StopIteration when appropriate. - field_name = self.child_iter.next() + field_name = next(self.child_iter) child = self.val["__base_"][field_name]["__value_"] self.count += 1 return ("[%d]" % self.count, child) @@ -311,12 +312,21 @@ class StdSharedPointerPrinter(object): return "%s is nullptr" % typename refcount = self.val["__cntrl_"] if refcount != 0: - usecount = refcount["__shared_owners_"] + 1 - weakcount = refcount["__shared_weak_owners_"] - if usecount == 0: - state = "expired, weak %d" % weakcount - else: - state = "count %d, weak %d" % (usecount, weakcount) + try: + usecount = refcount["__shared_owners_"] + 1 + weakcount = refcount["__shared_weak_owners_"] + if usecount == 0: + state = "expired, weak %d" % weakcount + else: + state = "count %d, weak %d" % (usecount, weakcount) + except: + # Debug info for a class with virtual functions is emitted + # in the same place as its key function. That means that + # for std::shared_ptr, __shared_owners_ is emitted into + # into libcxx.[so|a] itself, rather than into the shared_ptr + # instantiation point. So if libcxx.so was built without + # debug info, these fields will be missing. + state = "count ?, weak ? (libc++ missing debug info)" return "%s<%s> %s containing" % (typename, pointee_type, state) def __iter__(self): @@ -425,6 +435,7 @@ class StdBitsetPrinter(object): self.val = val self.n_words = int(self.val["__n_words"]) self.bits_per_word = int(self.val["__bits_per_word"]) + self.bit_count = self.val.type.template_argument(0) if self.n_words == 1: self.values = [int(self.val["__first_"])] else: @@ -435,21 +446,12 @@ class StdBitsetPrinter(object): typename = _prettify_typename(self.val.type) return "%s" % typename - def _byte_it(self, value): - index = -1 - while value: - index += 1 - will_yield = value % 2 - value /= 2 - if will_yield: - yield index - def _list_it(self): - for word_index in range(self.n_words): - current = self.values[word_index] - if current: - for n in self._byte_it(current): - yield ("[%d]" % (word_index * self.bits_per_word + n), 1) + for bit in range(self.bit_count): + word = math.floor(bit / self.bits_per_word) + word_bit = bit % self.bits_per_word + if self.values[word] & (1 << word_bit): + yield ("[%d]" % bit, 1) def __iter__(self): return self._list_it() diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 00de15dae24a2808249fec51aaac46cde1bda78b..342e15691eb90af6977c000c9cc1a30d9333d9c2 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -111,14 +111,14 @@ feature_test_macros = [ add_version_header(x) for x in [ "name": "__cpp_lib_atomic_wait", "values": { "c++20": 201907 }, "headers": ["atomic"], - "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", - "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + "depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)", + "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)", }, { "name": "__cpp_lib_barrier", "values": { "c++20": 201907 }, "headers": ["barrier"], - "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", - "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + "depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)", + "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)", }, { "name": "__cpp_lib_bind_front", "values": { "c++20": 201907 }, @@ -270,6 +270,8 @@ feature_test_macros = [ add_version_header(x) for x in [ "name": "__cpp_lib_filesystem", "values": { "c++17": 201703 }, "headers": ["filesystem"], + "depends": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)", + "internal_depends": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)" }, { "name": "__cpp_lib_gcd_lcm", "values": { "c++17": 201606 }, @@ -383,8 +385,8 @@ feature_test_macros = [ add_version_header(x) for x in [ "name": "__cpp_lib_latch", "values": { "c++20": 201907 }, "headers": ["latch"], - "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", - "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + "depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)", + "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)", }, { "name": "__cpp_lib_launder", "values": { "c++17": 201606 }, @@ -496,14 +498,14 @@ feature_test_macros = [ add_version_header(x) for x in [ "name": "__cpp_lib_semaphore", "values": { "c++20": 201907 }, "headers": ["semaphore"], - "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", - "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + "depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)", + "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)", }, { "name": "__cpp_lib_shared_mutex", "values": { "c++17": 201505 }, "headers": ["shared_mutex"], - "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", - "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + "depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)", + "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)", }, { "name": "__cpp_lib_shared_ptr_arrays", "values": { "c++17": 201611 }, @@ -516,8 +518,8 @@ feature_test_macros = [ add_version_header(x) for x in [ "name": "__cpp_lib_shared_timed_mutex", "values": { "c++14": 201402 }, "headers": ["shared_mutex"], - "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", - "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + "depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)", + "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)", }, { "name": "__cpp_lib_shift", "values": { "c++20": 201806 }, diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index b803347c2a8e3534491f3e96ce42ba3da9d5f8c9..6de2b5a2ed1039987814282c54bf5e513b49cc44 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -28,7 +28,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_B project(libcxxabi CXX C) set(PACKAGE_NAME libcxxabi) - set(PACKAGE_VERSION 11.0.0git) + set(PACKAGE_VERSION 12.0.1) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index 6bfc02d1537966b5d94695dfc0c434a64b9fb5fb..e5fca98f9271798a3476ca5c6a5c10cacaa01ffd 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -96,7 +96,6 @@ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ - X(UUIDOfExpr) \ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ @@ -2035,21 +2034,6 @@ public: } }; -// MSVC __uuidof extension, generated by clang in -fms-extensions mode. -class UUIDOfExpr : public Node { - Node *Operand; -public: - UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} - - template void match(Fn F) const { F(Operand); } - - void printLeft(OutputStream &S) const override { - S << "__uuidof("; - Operand->print(S); - S << ")"; - } -}; - class BoolExpr : public Node { bool Value; @@ -5013,6 +4997,43 @@ Node *AbstractManglingParser::parseExpr() { } } return nullptr; + case 'u': { + ++First; + Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); + if (!Name) + return nullptr; + // Special case legacy __uuidof mangling. The 't' and 'z' appear where the + // standard encoding expects a , and would be otherwise be + // interpreted as node 'short' or 'ellipsis'. However, neither + // __uuidof(short) nor __uuidof(...) can actually appear, so there is no + // actual conflict here. + if (Name->getBaseName() == "__uuidof") { + if (numLeft() < 2) + return nullptr; + if (*First == 't') { + ++First; + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make(Name, makeNodeArray(&Ty, &Ty + 1)); + } + if (*First == 'z') { + ++First; + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make(Name, makeNodeArray(&Ex, &Ex + 1)); + } + } + size_t ExprsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseTemplateArg(); + if (E == nullptr) + return E; + Names.push_back(E); + } + return make(Name, popTrailingNodeArray(ExprsBegin)); + } case '1': case '2': case '3': @@ -5024,21 +5045,6 @@ Node *AbstractManglingParser::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } - - if (consumeIf("u8__uuidoft")) { - Node *Ty = getDerived().parseType(); - if (!Ty) - return nullptr; - return make(Ty); - } - - if (consumeIf("u8__uuidofz")) { - Node *Ex = getDerived().parseExpr(); - if (!Ex) - return nullptr; - return make(Ex); - } - return nullptr; } diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index 3954fdba048e496d673225fd359d638678df70f8..512cc3928fdd672db49803bc16005409c403f58b 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -29776,8 +29776,18 @@ const char* cases[][2] = // Vendor extension types are substitution candidates. {"_Z1fu3fooS_", "f(foo, foo)"}, - {"_ZN3FooIXu8__uuidofzdeL_Z3sucEEEC1Ev", "Foo<__uuidof(*(suc))>::Foo()"}, - {"_ZN3FooIXu8__uuidoft13SomeUUIDClassEEC1Ev", "Foo<__uuidof(SomeUUIDClass)>::Foo()"}, + // alignof with type and expression, and __alignof__ with the same. + {"_Z2f1IiEvDTatT_E", "void f1(decltype(alignof (int)))"}, + {"_Z2f3IiEvDTazcvT_Li0EE", "void f3(decltype(alignof ((int)(0))))"}, + {"_Z2f2IiEvDTu11__alignof__T_EE", "void f2(decltype(__alignof__(int)))"}, + {"_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE", "void f4(decltype(__alignof__((int)(0))))"}, + + // Legacy nonstandard mangling for __uuidof. + {"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E", "void test_uuidofType(decltype(__uuidof(TestStruct)))"}, + {"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr(decltype(__uuidof(HasMember::member)))"}, + // Current __uuidof mangling using vendor extended expression. + {"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE", "void test_uuidofType(decltype(__uuidof(TestStruct)))"}, + {"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr(decltype(__uuidof(HasMember::member)))"}, // C++2a char8_t: {"_ZTSPDu", "typeinfo name for char8_t*"}, diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index 8ae32fbccf4e2aec02a916542e225c39a758eafd..570b8db906532d4ea97bc04fbcf5467929e52146 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -24,7 +24,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_B project(libunwind LANGUAGES C CXX ASM) set(PACKAGE_NAME libunwind) - set(PACKAGE_VERSION 12.0.0git) + set(PACKAGE_VERSION 12.0.1) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index f40bb258b9af2796ff7c80c04cb46d8a0be906f1..6f16fc7abc486ca4369467715d1b0f043631074b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -901,7 +901,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { continue; } - if (expr != R_ABS && expr != R_DTPREL && expr != R_RISCV_ADD) { + // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC + // sections. + if (expr != R_ABS && expr != R_DTPREL && expr != R_GOTPLTREL && + expr != R_RISCV_ADD) { std::string msg = getLocation(offset) + ": has non-ABS relocation " + toString(type) + " against symbol '" + toString(sym) + "'"; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 9a875bd7ec3e7fedb5b766a0e730c61d759842f1..70c36c63d10142b8a8bd872d80b944e696f1ab8d 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3110,7 +3110,9 @@ size_t VersionTableSection::getSize() const { void VersionTableSection::writeTo(uint8_t *buf) { buf += 2; for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) { - write16(buf, s.sym->versionId); + // Use the original versionId for an unfetched lazy symbol (undefined weak), + // which must be VER_NDX_GLOBAL (an undefined versioned symbol is an error). + write16(buf, s.sym->isLazy() ? VER_NDX_GLOBAL : s.sym->versionId); buf += 2; } } diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index e0b17ca3e030d0adb6bd3b28ead798ffeb35fcc8..24ed23bb2b7d4ba5c72f7df01bd54a0a0f977fbb 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -24,28 +24,124 @@ Non-comprehensive list of changes in this release ELF Improvements ---------------- -* ``--error-handling-script`` is added to allow for user-defined handlers upon +* ``--dependency-file`` has been added. (Similar to ``cc -M -MF``.) + (`D82437 `_) +* ``--error-handling-script`` has been added to allow for user-defined handlers upon missing libraries. (`D87758 `_) +* ``--exclude-libs`` can now localize defined version symbols and bitcode referenced libcall symbols. + (`D94280 `_) +* ``--gdb-index`` now works with DWARF v5 and ``--icf={safe,all}``. + (`D85579 `_) + (`D89751 `_) +* ``--gdb-index --emit-relocs`` can now be used together. + (`D94354 `_) +* ``--icf={safe,all}`` conservatively no longer fold text sections with LSDA. + Previously ICF on ``-fexceptions`` code could be unsafe. + (`D84610 `_) +* ``--icf={safe,all}`` can now fold two sections with relocations referencing aliased symbols. + (`D88830 `_) +* ``--lto-pseudo-probe-for-profiling`` has been added. + (`D95056 `_) +* ``--no-lto-whole-program-visibility`` has been added. + (`D92060 `_) +* ``--oformat-binary`` has been fixed to respect LMA. + (`D85086 `_) +* ``--reproduce`` includes ``--lto-sample-profile``, ``--just-symbols``, ``--call-graph-ordering-file``, ``--retain-symbols-file`` files. +* ``-r --gc-sections`` is now supported. + (`D84131 `_) +* A ``-u`` specified symbol will no longer change the binding to ``STB_WEAK``. + (`D88945 `_) +* ``--wrap`` support has been improved. + + If ``foo`` is not referenced, there is no longer an undefined symbol ``__wrap_foo``. + + If ``__real_foo`` is not referenced, there is no longer an undefined symbol ``foo``. +* ``SHF_LINK_ORDER`` sections can now have zero ``sh_link`` values. +* ``SHF_LINK_ORDER`` and non-``SHF_LINK_ORDER`` sections can now be mixed within an input section description. + (`D84001 `_) +* ``LOG2CEIL`` is now supported in linker scripts. + (`D84054 `_) +* ``DEFINED`` has been fixed to check whether the symbol is defined. + (`D83758 `_) +* An input section description may now have multiple ``SORT_*``. + The matched sections are ordered by radix sort with the keys being ``(SORT*, --sort-section, input order)``. + (`D91127 `_) +* Users can now provide a GNU style linker script to convert ``.ctors`` into ``.init_array``. + (`D91187 `_) +* An empty output section can now be discarded even if it is assigned to a program header. + (`D92301 `_) +* Non-``SHF_ALLOC`` sections now have larger file offsets than ``SHF_ALLOC`` sections. + (`D85867 `_) +* Some symbol versioning improvements. + + Defined ``foo@@v1`` now resolve undefined ``foo@v1`` (`D92259 `_) + + Undefined ``foo@v1`` now gets an error (`D92260 `_) +* The AArch64 port now has support for ``STO_AARCH64_VARIANT_PCS`` and ``DT_AARCH64_VARIANT_PCS``. + (`D93045 `_) +* The AArch64 port now has support for ``R_AARCH64_LD64_GOTPAGE_LO15``. +* The PowerPC64 port now detects missing R_PPC64_TLSGD/R_PPC64_TLSLD and disables TLS relaxation. + This allows linking with object files produced by very old IBM XL compilers. + (`D92959 `_) +* Many PowerPC PC-relative relocations are now supported. +* ``R_PPC_ADDR24`` and ``R_PPC64_ADDR16_HIGH`` are now supported. +* powerpcle is now supported. Tested with FreeBSD loader and freestanding. + (`D93917 `_) +* RISC-V: the first ``SHT_RISCV_ATTRIBUTES`` section is now retained. + (`D86309 `_) +* LTO pipeline now defaults to the new PM if the CMake variable ``ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER`` is on. + (`D92885 `_) Breaking changes ---------------- -* ... +* A COMMON symbol can now cause the fetch of an archive providing a ``STB_GLOBAL`` definition. + This behavior follows GNU ld newer than December 1999. + If you see ``duplicate symbol`` errors with the new behavior, check out `PR49226 `_. + (`D86142 `_) COFF Improvements ----------------- -* ... +* Error out clearly if creating a DLL with too many exported symbols. + (`D86701 `_) MinGW Improvements ------------------ -* ... +* Enabled dynamicbase by default. (`D86654 `_) -MachO Improvements +* Tolerate mismatches between COMDAT section sizes with different amount of + padding (produced by binutils) by inspecting the aux section definition. + (`D86659 `_) + +* Support setting the subsystem version via the subsystem argument. + (`D88804 `_) + +* Implemented the GNU -wrap option. + (`D89004 `_, + `D91689 `_) + +* Handle the ``--demangle`` and ``--no-demangle`` options. + (`D93950 `_) + + +Mach-O Improvements ------------------ -* Item 1. +We've gotten the new implementation of LLD for Mach-O to the point where it is +able to link large x86_64 programs, and we'd love to get some alpha testing on +it. The new Darwin back-end can be invoked as follows: + +.. code-block:: + clang -fuse-ld=lld.darwinnew /path/to/file.c + +To reach this point, we implemented numerous features, and it's easier to list +the major features we *haven't* yet completed: + +* LTO support +* Stack unwinding for exceptions +* Support for arm64, arm, and i386 architectures + +If you stumble upon an issue and it doesn't fall into one of these categories, +please file a bug report! + WebAssembly Improvements ------------------------ diff --git a/lld/test/ELF/lto/parallel.ll b/lld/test/ELF/lto/parallel.ll index d9cb4fed7bfae1b10f8eeae1200f83500f3cdd3a..d89431e8b4a16da1a104c96ae9afd7c73bf7e0a8 100644 --- a/lld/test/ELF/lto/parallel.ll +++ b/lld/test/ELF/lto/parallel.ll @@ -14,7 +14,7 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK0-NOT: bar ; CHECK0: T foo ; CHECK0-NOT: bar -define void @foo() { +define void @foo() mustprogress { call void @bar() ret void } @@ -22,7 +22,7 @@ define void @foo() { ; CHECK1-NOT: foo ; CHECK1: T bar ; CHECK1-NOT: foo -define void @bar() { +define void @bar() mustprogress { call void @foo() ret void } diff --git a/lld/test/ELF/non-abs-reloc.s b/lld/test/ELF/non-abs-reloc.s index 72a65424ed1f46af4884e85775de5dfe24207187..82f913efe4d82aa2770f471ea77feafadd5c9bd1 100644 --- a/lld/test/ELF/non-abs-reloc.s +++ b/lld/test/ELF/non-abs-reloc.s @@ -1,17 +1,17 @@ // REQUIRES: x86 // RUN: split-file %s %t -// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/asm -o %t.o -// RUN: ld.lld -T %t/lds %t.o -o %t.exe 2>&1 | FileCheck %s -// CHECK: warning: {{.*}}.o:(.nonalloc1+0x1): has non-ABS relocation R_X86_64_PC32 against symbol '_start' -// CHECK-NEXT: warning: {{.*}}.o:(.nonalloc1+0x6): has non-ABS relocation R_X86_64_PC32 against symbol '_start' +// RUN: llvm-mc -filetype=obj -triple=i386 %t/asm -o %t.o +// RUN: ld.lld -T %t/lds %t.o -o %t.exe 2>&1 | FileCheck %s --implicit-check-not=warning: --implicit-check-not=error: +// CHECK: warning: {{.*}}.o:(.nonalloc1+0x1): has non-ABS relocation R_386_PC32 against symbol '_start' +// CHECK-NEXT: warning: {{.*}}.o:(.nonalloc1+0x6): has non-ABS relocation R_386_PC32 against symbol '_start' // RUN: llvm-objdump -D --no-show-raw-insn %t.exe | FileCheck --check-prefix=DISASM %s // DISASM: Disassembly of section .nonalloc: // DISASM-EMPTY: // DISASM-NEXT: <.nonalloc>: // DISASM-NEXT: 0: nop -// DISASM-NEXT: 1: callq 0x0 -// DISASM-NEXT: 6: callq 0x0 +// DISASM-NEXT: 1: calll 0x0 +// DISASM-NEXT: 6: calll 0x0 //--- lds SECTIONS { @@ -20,6 +20,7 @@ SECTIONS { //--- asm .globl _start _start: +.L0: nop .section .nonalloc0 @@ -30,3 +31,8 @@ _start: .long _start - . - 4 .byte 0xe8 .long _start - . - 4 + +// GCC may relocate DW_AT_GNU_call_site_value with R_386_GOTOFF. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98946 +.section .debug_info + .long .L0@gotoff diff --git a/lld/test/ELF/version-script-weak.s b/lld/test/ELF/version-script-weak.s index 7c902eb98bf4db6c7bf638dd9e228425dc8a3c1f..cfa2455ee2bd226ad5b257e2566741b11a787570 100644 --- a/lld/test/ELF/version-script-weak.s +++ b/lld/test/ELF/version-script-weak.s @@ -24,6 +24,19 @@ # CHECK-NEXT: Section: Undefined # CHECK-NEXT: } +## The version of an unfetched lazy symbol is VER_NDX_GLOBAL. It is not affected by version scripts. +# RUN: echo "v1 { *; };" > %t2.script +# RUN: ld.lld -shared --version-script %t2.script %t.o --start-lib %t1.o --end-lib -o %t2.so +# RUN: llvm-readelf --dyn-syms %t2.so | FileCheck %s --check-prefix=CHECK2 + +# CHECK2: NOTYPE WEAK DEFAULT UND foo{{$}} + +# RUN: ld.lld -shared --soname=tshared --version-script %t2.script %t1.o -o %tshared.so +# RUN: ld.lld -shared --version-script %t2.script %t.o --start-lib %t1.o --end-lib %tshared.so -o %t3.so +# RUN: llvm-readelf --dyn-syms %t3.so | FileCheck %s --check-prefix=CHECK3 + +# CHECK3: NOTYPE WEAK DEFAULT UND foo@v1 + .text callq foo@PLT .weak foo diff --git a/lld/test/lit.cfg.py b/lld/test/lit.cfg.py index 8e31fd3977f9a44071c147ef3c6d8109dfc1b4f4..670f41f0b63132e64e22e5e0458d6aa59a664cec 100644 --- a/lld/test/lit.cfg.py +++ b/lld/test/lit.cfg.py @@ -101,11 +101,13 @@ if config.sizeof_void_p == 8: tar_executable = lit.util.which('tar', config.environment['PATH']) if tar_executable: + env = os.environ + env['LANG'] = 'C' tar_version = subprocess.Popen( [tar_executable, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, - env={'LANG': 'C'}) + env=env) sout, _ = tar_version.communicate() if 'GNU tar' in sout.decode(): config.available_features.add('gnutar') diff --git a/lld/test/wasm/lto/parallel.ll b/lld/test/wasm/lto/parallel.ll index a93c3558d9694c7c619e07d57db4e0a43a3e4a25..261cf2ef7dae326057118e891c94215d5dcbfee4 100644 --- a/lld/test/wasm/lto/parallel.ll +++ b/lld/test/wasm/lto/parallel.ll @@ -10,7 +10,7 @@ target triple = "wasm32-unknown-unknown-wasm" ; CHECK0-NOT: bar ; CHECK0: T foo ; CHECK0-NOT: bar -define void @foo() { +define void @foo() mustprogress { call void @bar() ret void } @@ -18,7 +18,7 @@ define void @foo() { ; CHECK1-NOT: foo ; CHECK1: T bar ; CHECK1-NOT: foo -define void @bar() { +define void @bar() mustprogress { call void @foo() ret void } diff --git a/lldb/docs/man/lldb.rst b/lldb/docs/man/lldb.rst index 6dca15fa35dc97e968057c9358cf72db937eb66a..b75288db380dec8879667f6f74ef92d41c492586 100644 --- a/lldb/docs/man/lldb.rst +++ b/lldb/docs/man/lldb.rst @@ -256,11 +256,11 @@ executable. To disambiguate between arguments passed to lldb and arguments passed to the debugged executable, arguments starting with a - must be passed after --. - lldb --arch x86_64 /path/to/program program argument -- --arch arvm7 + lldb --arch x86_64 /path/to/program program argument -- --arch armv7 For convenience, passing the executable after -- is also supported. - lldb --arch x86_64 -- /path/to/program program argument --arch arvm7 + lldb --arch x86_64 -- /path/to/program program argument --arch armv7 Passing one of the attach options causes :program:`lldb` to immediately attach to the given process. diff --git a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py index 055b5a5bed8787ad4c9afb3ea1a8c5e3205ccfa3..047cc317596f224d19304676c0af332c9a64884d 100644 --- a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py +++ b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py @@ -33,20 +33,30 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): with open(fifo_file, "r") as file: return file.readline() + def isTestSupported(self): + # For some strange reason, this test fails on python3.6 + if not (sys.version_info.major == 3 and sys.version_info.minor >= 7): + return False + try: + # We skip this test for debug builds because it takes too long parsing lldb's own + # debug info. Release builds are fine. + # Checking the size of the lldb-vscode binary seems to be a decent proxy for a quick + # detection. It should be far less than 1 MB in Release builds. + if os.path.getsize(os.environ["LLDBVSCODE_EXEC"]) < 1000000: + return True + except: + return False + @skipIfWindows @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_runInTerminal(self): + if not self.isTestSupported(): + return ''' Tests the "runInTerminal" reverse request. It makes sure that the IDE can launch the inferior with the correct environment variables and arguments. ''' - if "debug" in str(os.environ["LLDBVSCODE_EXEC"]).lower(): - # We skip this test for debug builds because it takes too long parsing lldb's own - # debug info. Release builds are fine. - # Checking this environment variable seems to be a decent proxy for a quick - # detection - return program = self.getBuildArtifact("a.out") source = 'main.c' self.build_and_launch( @@ -77,6 +87,8 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_runInTerminalInvalidTarget(self): + if not self.isTestSupported(): + return self.build_and_create_debug_adaptor() response = self.launch( "INVALIDPROGRAM", stopOnEntry=True, runInTerminal=True, args=["foobar"], env=["FOO=bar"], expectFailure=True) @@ -88,6 +100,8 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_missingArgInRunInTerminalLauncher(self): + if not self.isTestSupported(): + return proc = subprocess.run([self.lldbVSCodeExec, "--launch-target", "INVALIDPROGRAM"], capture_output=True, universal_newlines=True) self.assertTrue(proc.returncode != 0) @@ -97,6 +111,8 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_FakeAttachedRunInTerminalLauncherWithInvalidProgram(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -115,6 +131,8 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_FakeAttachedRunInTerminalLauncherWithValidProgram(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -132,6 +150,8 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_FakeAttachedRunInTerminalLauncherAndCheckEnvironment(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -150,6 +170,8 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_NonAttachedRunInTerminalLauncher(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index e4a60127b65edbcd9b5328d4118ca5f322a8edff..210a712f97414f77d2669899b644bed121946cda 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -751,11 +751,11 @@ EXAMPLES: arguments passed to the debugged executable, arguments starting with a - must be passed after --. - lldb --arch x86_64 /path/to/program program argument -- --arch arvm7 + lldb --arch x86_64 /path/to/program program argument -- --arch armv7 For convenience, passing the executable after -- is also supported. - lldb --arch x86_64 -- /path/to/program program argument --arch arvm7 + lldb --arch x86_64 -- /path/to/program program argument --arch armv7 Passing one of the attach options causes lldb to immediately attach to the given process. diff --git a/lldb/tools/lldb-vscode/FifoFiles.cpp b/lldb/tools/lldb-vscode/FifoFiles.cpp index b69970ec0168b64f3d6020d1a45772540e473958..4b14fb16f96c12f2ecbd677a3e212bd696b49a07 100644 --- a/lldb/tools/lldb-vscode/FifoFiles.cpp +++ b/lldb/tools/lldb-vscode/FifoFiles.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -#if !defined(WIN32) +#include "FifoFiles.h" + +#if !defined(_WIN32) #include #include #include @@ -21,8 +23,6 @@ #include "lldb/lldb-defines.h" -#include "FifoFiles.h" - using namespace llvm; namespace lldb_vscode { @@ -30,13 +30,13 @@ namespace lldb_vscode { FifoFile::FifoFile(StringRef path) : m_path(path) {} FifoFile::~FifoFile() { -#if !defined(WIN32) +#if !defined(_WIN32) unlink(m_path.c_str()); #endif }; Expected> CreateFifoFile(StringRef path) { -#if defined(WIN32) +#if defined(_WIN32) return createStringError(inconvertibleErrorCode(), "Unimplemented"); #else if (int err = mkfifo(path.data(), 0600)) diff --git a/lldb/tools/lldb-vscode/FifoFiles.h b/lldb/tools/lldb-vscode/FifoFiles.h index 891b6f5746010ad24422933a214f862464201c5b..f186f65e86c43e7ffbf1d2c19798f80cfe6aa613 100644 --- a/lldb/tools/lldb-vscode/FifoFiles.h +++ b/lldb/tools/lldb-vscode/FifoFiles.h @@ -9,6 +9,7 @@ #ifndef LLDB_TOOLS_LLDB_VSCODE_FIFOFILES_H #define LLDB_TOOLS_LLDB_VSCODE_FIFOFILES_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX #include "llvm/Support/Error.h" #include "JSONUtils.h" diff --git a/lldb/tools/lldb-vscode/IOStream.cpp b/lldb/tools/lldb-vscode/IOStream.cpp index 4b11b90b4c2e829027f5f8bea8ce939fe343b652..cd22d906c14c6df24c5a24d35e959d74d659cafd 100644 --- a/lldb/tools/lldb-vscode/IOStream.cpp +++ b/lldb/tools/lldb-vscode/IOStream.cpp @@ -8,7 +8,7 @@ #include "IOStream.h" -#if defined(_WIN32) +#if defined(_WIN32) #include #else #include diff --git a/lldb/tools/lldb-vscode/IOStream.h b/lldb/tools/lldb-vscode/IOStream.h index 603ae9adcc2a1d4fb8fb703e88f672a79058634d..0eb9b6fefb0dca4e858f55db581b2a534de01149 100644 --- a/lldb/tools/lldb-vscode/IOStream.h +++ b/lldb/tools/lldb-vscode/IOStream.h @@ -9,6 +9,8 @@ #ifndef LLDB_TOOLS_LLDB_VSCODE_IOSTREAM_H #define LLDB_TOOLS_LLDB_VSCODE_IOSTREAM_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX + #if defined(_WIN32) // We need to #define NOMINMAX in order to skip `min()` and `max()` macro // definitions that conflict with other system headers. diff --git a/lldb/tools/lldb-vscode/RunInTerminal.cpp b/lldb/tools/lldb-vscode/RunInTerminal.cpp index 4db2806924ca0cf0f191090ca1c57b22a45820df..2126563d9e9615634b5c3da0889430bd1fccc90d 100644 --- a/lldb/tools/lldb-vscode/RunInTerminal.cpp +++ b/lldb/tools/lldb-vscode/RunInTerminal.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -#if !defined(WIN32) +#include "RunInTerminal.h" + +#if !defined(_WIN32) #include #include #include @@ -21,8 +23,6 @@ #include "lldb/lldb-defines.h" -#include "RunInTerminal.h" - using namespace llvm; namespace lldb_vscode { diff --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h index 8e7dfc0789344658635fa53799b4b72666daebf6..a2e1cac8ecf9168fd6519ea63d0ea757f32dd389 100644 --- a/lldb/tools/lldb-vscode/VSCode.h +++ b/lldb/tools/lldb-vscode/VSCode.h @@ -9,6 +9,8 @@ #ifndef LLDB_TOOLS_LLDB_VSCODE_VSCODE_H #define LLDB_TOOLS_LLDB_VSCODE_VSCODE_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX + #include #include #include diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp index c581b9b4a9a0dfe594d5aa9f1c1d038664069cf8..9469690cd7db5b5d4f34bd177e14cc4c0473cf31 100644 --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "VSCode.h" + #include #include #include @@ -52,7 +54,6 @@ #include "JSONUtils.h" #include "LLDBUtils.h" -#include "VSCode.h" #if defined(_WIN32) #ifndef PATH_MAX @@ -3002,8 +3003,8 @@ EXAMPLES: // emitted to the debug adaptor. void LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg, llvm::StringRef comm_file, char *argv[]) { -#if defined(WIN_32) - llvm::errs() << "runInTerminal is not supported on Windows\n"; +#if defined(_WIN32) + llvm::errs() << "runInTerminal is only supported on POSIX systems\n"; exit(EXIT_FAILURE); #else RunInTerminalLauncherCommChannel comm_channel(comm_file); diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 454ec561af9a4786f9eff051793a4f9a2aafdcb1..28ccef34d8fc74a28edaab7752319882e1523e12 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -11,10 +11,10 @@ if(NOT DEFINED LLVM_VERSION_MINOR) set(LLVM_VERSION_MINOR 0) endif() if(NOT DEFINED LLVM_VERSION_PATCH) - set(LLVM_VERSION_PATCH 0) + set(LLVM_VERSION_PATCH 1) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX git) + set(LLVM_VERSION_SUFFIX "") endif() if (NOT PACKAGE_VERSION) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index de8431fe3908e6a18d1823ae9a1ce72ec1ba1e02..542a505bfd2e66ca9919741d488b3a42a8c57614 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -92,6 +92,29 @@ Changes to TableGen uses the "`...`" range punctuation (e.g., ``{0...9}``). The hyphen syntax is deprecated. +Changes to the AArch64 Backend +-------------------------- + +During this release ... + +* Lots of improvements to generation of Windows unwind data; the unwind + data is optimized and written in packed form where possible, reducing + the size of unwind data (pdata and xdata sections) by around 60% + compared with LLVM 11. The generation of prologs/epilogs is tweaked + when targeting Windows, to increase the chances of being able to use + the packed unwind info format. + +* Support for creating Windows unwind data using ``.seh_*`` assembler + directives. + +* Produce proper assembly output for the Windows target, including + ``:lo12:`` relocation specifiers, to allow the assembly output + to actually be assembled. + +* Changed the assembly comment string for MSVC targets to ``//`` (consistent + with the MinGW and ELF targets), freeing up ``;`` to be used as + statement separator. + Changes to the ARM Backend -------------------------- @@ -106,7 +129,75 @@ During this release ... Changes to the PowerPC Target ----------------------------- -During this release ... +Optimization: + +* Made improvements to loop unroll-and-jam including fix to respect user + provided #pragma unroll-and-jam for loops on targets other than ARM. +* Improved PartialInliner allowing it to handle code regions in a switch + statements. +* Improved PGO support on AIX by building and linking with compiler-rt profile + library. +* Add support for Epilogue Vectorization and enabled it by default. + +CodeGen: + +* POWER10 support + * Implementation of PC Relative addressing in LLD including the associated + linker optimizations. + * Add support for the new matrix multiplication (MMA) instructions to Clang + and LLVM. + * Implementation of Power10 builtins. + +* Scheduling enhancements + * Add a new algorithm to cluster more loads/stores if the DAG is not too + complicated. + * Enable the PowerPC scheduling heuristic for Power10. + +* Target dependent passes tuning + * Enhance LoopStrengthReduce/PPCLoopInstrFormPrep pass for PowerPC, + especially for P10 intrinsics. + * Enhance machine combiner pass to reduce register pressure for PowerPC. + * Improve MachineSink to do more sinking based on register pressure and alias + analysis. + +* General improvements + * Complete the constrained floating point operations support. + * Improve the llvm-exegesis support. + * Improve the stack clash protection to probe the gap between stackptr and + realigned stackptr. + * Improve the IEEE long double support for Power8. + * Enable MemorySSA for LoopSink. + * Enhance LLVM debugging functionality via options such as -print-changed and + -print-before-changed. + * Add builtins for Power9 (i.e. darn, xvtdiv, xvtsqrt etc). + * Add options to disable all or part of LoopIdiomRecognizePass. + * Add support for printing the DDG in DOT form allowing for visual inspection + of the Data Dependence Graph. + * Remove the QPX support. + * Significant number of bug fixes including all the fixes necessary to + achieve a clean test run for Julia. + +AIX Support: + +* Compiler-rt support + * Add support for building compiler-rt for AIX and 32-bit Power targets. + * Made compiler-rt the default rtlib for AIX. + +* General Improvements + * Enable the AIX extended AltiVec ABI under option -mabi=vec-extabi. + * Add partial C99 complex type support. + * Implemente traceback table for functions (encodes vector information, + emits exception handling). + * Implemente code generation for C++ dynamic initialization and finalization. + of non-local variables for use with the -bcdtors option of the AIX linker. + * Add new option -mignore-xcoff-visibility. + * Enable explicit sections on AIX. + * Enable -f[no-]data-sections on AIX and set -fdata-sections to be the default + on AIX. + * Enable -f[no-]function-sections. + * Add support for relocation generation using the large code model. + * Add pragma align natural and sorted out pragma pack stack effect. + Changes to the X86 Target ------------------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 8274213aa839bd7ac9135a9d6549c3e75a89cf5e..2901ab715810fa43b9a6604db41b94bd909a4fda 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -160,10 +160,10 @@ typedef enum { LLVMVectorTypeKind, /**< Fixed width SIMD vector type */ LLVMMetadataTypeKind, /**< Metadata */ LLVMX86_MMXTypeKind, /**< X86 MMX */ - LLVMX86_AMXTypeKind, /**< X86 AMX */ LLVMTokenTypeKind, /**< Tokens */ LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */ - LLVMBFloatTypeKind /**< 16 bit brain floating point type */ + LLVMBFloatTypeKind, /**< 16 bit brain floating point type */ + LLVMX86_AMXTypeKind /**< X86 AMX */ } LLVMTypeKind; typedef enum { @@ -270,7 +270,6 @@ typedef enum { LLVMConstantVectorValueKind, LLVMUndefValueValueKind, - LLVMPoisonValueValueKind, LLVMConstantAggregateZeroValueKind, LLVMConstantDataArrayValueKind, LLVMConstantDataVectorValueKind, @@ -283,6 +282,7 @@ typedef enum { LLVMInlineAsmValueKind, LLVMInstructionValueKind, + LLVMPoisonValueValueKind } LLVMValueKind; typedef enum { @@ -604,6 +604,17 @@ unsigned LLVMGetEnumAttributeKind(LLVMAttributeRef A); */ uint64_t LLVMGetEnumAttributeValue(LLVMAttributeRef A); +/** + * Create a type attribute + */ +LLVMAttributeRef LLVMCreateTypeAttribute(LLVMContextRef C, unsigned KindID, + LLVMTypeRef type_ref); + +/** + * Get the type attribute's value. + */ +LLVMTypeRef LLVMGetTypeAttributeValue(LLVMAttributeRef A); + /** * Create a string attribute. */ @@ -626,6 +637,7 @@ const char *LLVMGetStringAttributeValue(LLVMAttributeRef A, unsigned *Length); */ LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A); LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A); +LLVMBool LLVMIsTypeAttribute(LLVMAttributeRef A); /** * Obtain a Type from a context by its registered name. diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h index 183107c148a6d2e128d65867425fb97a1461e783..9beef44c89dd5ed2b49fbd320df437e42b6a5f0b 100644 --- a/llvm/include/llvm-c/Orc.h +++ b/llvm/include/llvm-c/Orc.h @@ -339,8 +339,7 @@ LLVMErrorRef LLVMOrcResourceTrackerRemove(LLVMOrcResourceTrackerRef RT); * ownership has not been passed to a JITDylib (e.g. because some error * prevented the client from calling LLVMOrcJITDylibAddGenerator). */ -void LLVMOrcDisposeDefinitionGenerator( - LLVMOrcDefinitionGeneratorRef DG); +void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG); /** * Dispose of a MaterializationUnit. @@ -388,7 +387,9 @@ LLVMOrcExecutionSessionCreateJITDylib(LLVMOrcExecutionSessionRef ES, * Returns the JITDylib with the given name, or NULL if no such JITDylib * exists. */ -LLVMOrcJITDylibRef LLVMOrcExecutionSessionGetJITDylibByName(const char *Name); +LLVMOrcJITDylibRef +LLVMOrcExecutionSessionGetJITDylibByName(LLVMOrcExecutionSessionRef ES, + const char *Name); /** * Return a reference to a newly created resource tracker associated with JD. diff --git a/llvm/include/llvm/ADT/Any.h b/llvm/include/llvm/ADT/Any.h index 0aded628cda4ae6dec4bdc4511d929a75d170f76..1e3abca7067928c2e7dec4b7663d77a95b6cb98f 100644 --- a/llvm/include/llvm/ADT/Any.h +++ b/llvm/include/llvm/ADT/Any.h @@ -23,7 +23,12 @@ namespace llvm { -class Any { +class LLVM_EXTERNAL_VISIBILITY Any { + + // The `Typeid::Id` static data member below is a globally unique + // identifier for the type `T`. It is explicitly marked with default + // visibility so that when `-fvisibility=hidden` is used, the loader still + // merges duplicate definitions across DSO boundaries. template struct TypeId { static const char Id; }; struct StorageBase { diff --git a/llvm/include/llvm/Analysis/AssumptionCache.h b/llvm/include/llvm/Analysis/AssumptionCache.h index 0ef63dc68e1ca9a923f21989283c1795fd3ce445..c4602d3449c0c30886e272e62e4d9a960bd38856 100644 --- a/llvm/include/llvm/Analysis/AssumptionCache.h +++ b/llvm/include/llvm/Analysis/AssumptionCache.h @@ -45,7 +45,7 @@ public: enum : unsigned { ExprResultIdx = std::numeric_limits::max() }; struct ResultElem { - WeakTrackingVH Assume; + WeakVH Assume; /// contains either ExprResultIdx or the index of the operand bundle /// containing the knowledge. diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h index 81c1d6aad49a1bdb2dcfb8b32dda5f06f04075be..26bf4ab2618ce698bda4a61d8963b98421985035 100644 --- a/llvm/include/llvm/CodeGen/FastISel.h +++ b/llvm/include/llvm/CodeGen/FastISel.h @@ -490,7 +490,10 @@ protected: /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - /// Test whether the given value has exactly one use. + /// Test whether the register associated with this value has exactly one use, + /// in which case that single use is killing. Note that multiple IR values + /// may map onto the same register, in which case this is not the same as + /// checking that an IR value has one use. bool hasTrivialKill(const Value *V); /// Create a machine mem operand from the given instruction. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index c3b494e94ff1dc833dd7191901f0a2520673cdf4..4a982b00125d0c9ff649d4eb48164ce1db68f9d6 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -316,6 +316,7 @@ public: LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); + LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index 6bbe2d03f9e58bc5d78464674614e53d744540d5..f8d97c2c07a6f5e6ae089c2cdea80d79f68216a1 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -1156,6 +1156,10 @@ public: return getOpcode() == TargetOpcode::CFI_INSTRUCTION; } + bool isPseudoProbe() const { + return getOpcode() == TargetOpcode::PSEUDO_PROBE; + } + // True if the instruction represents a position in the function. bool isPosition() const { return isLabel() || isCFIInstruction(); } @@ -1165,6 +1169,9 @@ public: bool isDebugInstr() const { return isDebugValue() || isDebugLabel() || isDebugRef(); } + bool isDebugOrPseudoInstr() const { + return isDebugInstr() || isPseudoProbe(); + } bool isDebugOffsetImm() const { return getDebugOffset().isImm(); } diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index c3221aac8eea404e8285d04cd18b49a4601899a3..40115fbd2f1582dfc17ad02d3ce53d00cc9c8f48 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -2785,6 +2785,10 @@ public: return false; } + /// Does this target require the clearing of high-order bits in a register + /// passed to the fp16 to fp conversion library function. + virtual bool shouldKeepZExtForFP16Conv() const { return false; } + //===--------------------------------------------------------------------===// // Runtime Library hooks // diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 39ae53c4e7fe58e821151f621840b72f86b8dcda..cf4c827b9267f90951cd891cccbf3e932f5a5318 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -111,6 +111,16 @@ public: return AttributeSpecs[idx].Attr; } + bool getAttrIsImplicitConstByIndex(uint32_t idx) const { + assert(idx < AttributeSpecs.size()); + return AttributeSpecs[idx].isImplicitConst(); + } + + int64_t getAttrImplicitConstValueByIndex(uint32_t idx) const { + assert(idx < AttributeSpecs.size()); + return AttributeSpecs[idx].getImplicitConstValue(); + } + /// Get the index of the specified attribute. /// /// Searches the this abbreviation declaration for the index of the specified diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index 6bfc02d1537966b5d94695dfc0c434a64b9fb5fb..e5fca98f9271798a3476ca5c6a5c10cacaa01ffd 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -96,7 +96,6 @@ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ - X(UUIDOfExpr) \ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ @@ -2035,21 +2034,6 @@ public: } }; -// MSVC __uuidof extension, generated by clang in -fms-extensions mode. -class UUIDOfExpr : public Node { - Node *Operand; -public: - UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} - - template void match(Fn F) const { F(Operand); } - - void printLeft(OutputStream &S) const override { - S << "__uuidof("; - Operand->print(S); - S << ")"; - } -}; - class BoolExpr : public Node { bool Value; @@ -5013,6 +4997,43 @@ Node *AbstractManglingParser::parseExpr() { } } return nullptr; + case 'u': { + ++First; + Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); + if (!Name) + return nullptr; + // Special case legacy __uuidof mangling. The 't' and 'z' appear where the + // standard encoding expects a , and would be otherwise be + // interpreted as node 'short' or 'ellipsis'. However, neither + // __uuidof(short) nor __uuidof(...) can actually appear, so there is no + // actual conflict here. + if (Name->getBaseName() == "__uuidof") { + if (numLeft() < 2) + return nullptr; + if (*First == 't') { + ++First; + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make(Name, makeNodeArray(&Ty, &Ty + 1)); + } + if (*First == 'z') { + ++First; + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make(Name, makeNodeArray(&Ex, &Ex + 1)); + } + } + size_t ExprsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseTemplateArg(); + if (E == nullptr) + return E; + Names.push_back(E); + } + return make(Name, popTrailingNodeArray(ExprsBegin)); + } case '1': case '2': case '3': @@ -5024,21 +5045,6 @@ Node *AbstractManglingParser::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } - - if (consumeIf("u8__uuidoft")) { - Node *Ty = getDerived().parseType(); - if (!Ty) - return nullptr; - return make(Ty); - } - - if (consumeIf("u8__uuidofz")) { - Node *Ex = getDerived().parseExpr(); - if (!Ex) - return nullptr; - return make(Ex); - } - return nullptr; } diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 844046167975960f8902f625cdbaf123d32d71a3..75d360bf4237a4b728863de84acb34fac25cf109 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -375,7 +375,7 @@ __OMP_RTL(__kmpc_init_allocator, false, /* omp_allocator_handle_t */ VoidPtr, __OMP_RTL(__kmpc_destroy_allocator, false, Void, /* Int */ Int32, /* omp_allocator_handle_t */ VoidPtr) -__OMP_RTL(__kmpc_push_target_tripcount, false, Void, IdentPtr, Int64, Int64) +__OMP_RTL(__kmpc_push_target_tripcount_mapper, false, Void, IdentPtr, Int64, Int64) __OMP_RTL(__tgt_target_mapper, false, Int32, IdentPtr, Int64, VoidPtr, Int32, VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) __OMP_RTL(__tgt_target_nowait_mapper, false, Int32, IdentPtr, Int64, VoidPtr, Int32, @@ -844,7 +844,7 @@ __OMP_RTL_ATTRS(__kmpc_free, AllocAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__kmpc_init_allocator, DefaultAttrs, ReturnPtrAttrs, {}) __OMP_RTL_ATTRS(__kmpc_destroy_allocator, AllocAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_push_target_tripcount_mapper, SetterAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__tgt_target_mapper, ForkAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__tgt_target_nowait_mapper, ForkAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__tgt_target_teams_mapper, ForkAttrs, AttributeSet(), {}) diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h index 0190aca27b724cfe7458660157a081c734b44d1f..71692c7460155c51876bad11622b753a3aeb4ab2 100644 --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -214,6 +214,10 @@ public: /// both must either be scalars or vectors with the same element count. If no /// changes are made, the constant C is returned. static Constant *mergeUndefsWith(Constant *C, Constant *Other); + + /// Return true if a constant is ConstantData or a ConstantAggregate or + /// ConstantExpr that contain only ConstantData. + bool isManifestConstant() const; }; } // end namespace llvm diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index f42ef48de6b3c25b467ac04b0b3bda72d28d8275..955ac8e537fe1838a8a650014c1d868aa9a21f31 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1757,9 +1757,6 @@ public: return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } - /// Returns true if this function is guaranteed to return. - bool willReturn() const { return hasFnAttr(Attribute::WillReturn); } - void setOnlyReadsMemory() { addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly); } diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index d2a55f89fac98a55fe11fbaf7729e0342c18927f..b99dc62bbb9de86f4553c3c07c63acc49e190412 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -633,6 +633,10 @@ public: /// generated program. bool isSafeToRemove() const; + /// Return true if the instruction will return (unwinding is considered as + /// a form of returning control flow here). + bool willReturn() const; + /// Return true if the instruction is a variety of EH-block. bool isEHPad() const { switch (getOpcode()) { @@ -650,6 +654,9 @@ public: /// llvm.lifetime.end marker. bool isLifetimeStartOrEnd() const; + /// Return true if the instruction is a DbgInfoIntrinsic or PseudoProbeInst. + bool isDebugOrPseudoInst() const; + /// Return a pointer to the next non-debug instruction in the same basic /// block as 'this', or nullptr if no such instruction exists. Skip any pseudo /// operations if \c SkipPseudoOp is true. diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index 9d68f3fdde6c24e47df1ec3c08116d53ac0acdbb..df3a1d568756764469b123b529d8909fcebb5b49 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -981,12 +981,16 @@ public: return cast(const_cast(getArgOperand(0))); } + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(1))); + } + ConstantInt *getAttributes() const { return cast(const_cast(getArgOperand(2))); } - ConstantInt *getIndex() const { - return cast(const_cast(getArgOperand(1))); + ConstantInt *getFactor() const { + return cast(const_cast(getArgOperand(3))); } }; diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index b2bfc6e6f9e6a3558eeab83425530f7fb5be5982..21307ed1bd91fe3b9b5cdcffe751ee8a6c0aff40 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1298,7 +1298,7 @@ def int_sideeffect : DefaultAttrsIntrinsic<[], [], [IntrInaccessibleMemOnly, Int // Like the sideeffect intrinsic defined above, this intrinsic is treated by the // optimizer as having opaque side effects so that it won't be get rid of or moved // out of the block it probes. -def int_pseudoprobe : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], +def int_pseudoprobe : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrInaccessibleMemOnly, IntrWillReturn]>; // Intrinsics to support half precision floating point format diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td index ab5b09b72ac335de17b78b02f2f2488dcc5f93c4..c4056895f68e688de1e109afdb1e69163e165d00 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -790,6 +790,9 @@ let TargetPrefix = "riscv" in { defm vsoxei : RISCVIStore; defm vsuxei : RISCVIStore; + def int_riscv_vle1 : RISCVUSLoad; + def int_riscv_vse1 : RISCVUSStore; + defm vamoswap : RISCVAMO; defm vamoadd : RISCVAMO; defm vamoxor : RISCVAMO; @@ -940,8 +943,8 @@ let TargetPrefix = "riscv" in { defm vfwnmsac : RISCVTernaryWide; defm vfsqrt : RISCVUnaryAA; - defm vfrsqrte7 : RISCVUnaryAA; - defm vfrece7 : RISCVUnaryAA; + defm vfrsqrt7 : RISCVUnaryAA; + defm vfrec7 : RISCVUnaryAA; defm vfmin : RISCVBinaryAAX; defm vfmax : RISCVBinaryAAX; diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h index 0b87416befe92bbe08a0a25ddc29f9f32ed73900..9a4480b75a30f536e4c36f29572a4bc34a8cdd56 100644 --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -667,6 +667,12 @@ struct AAMDNodes { /// The tag specifying the noalias scope. MDNode *NoAlias = nullptr; + // Shift tbaa Metadata node to start off bytes later + static MDNode *ShiftTBAA(MDNode *M, size_t off); + + // Shift tbaa.struct Metadata node to start off bytes later + static MDNode *ShiftTBAAStruct(MDNode *M, size_t off); + /// Given two sets of AAMDNodes that apply to the same pointer, /// give the best AAMDNodes that are compatible with both (i.e. a set of /// nodes whose allowable aliasing conclusions are a subset of those @@ -680,6 +686,18 @@ struct AAMDNodes { Result.NoAlias = Other.NoAlias == NoAlias ? NoAlias : nullptr; return Result; } + + /// Create a new AAMDNode that describes this AAMDNode after applying a + /// constant offset to the start of the pointer + AAMDNodes shift(size_t Offset) { + AAMDNodes Result; + Result.TBAA = TBAA ? ShiftTBAA(TBAA, Offset) : nullptr; + Result.TBAAStruct = + TBAAStruct ? ShiftTBAAStruct(TBAAStruct, Offset) : nullptr; + Result.Scope = Scope; + Result.NoAlias = NoAlias; + return Result; + } }; // Specialize DenseMapInfo for AAMDNodes. diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h index acfacbd6c74e6d7bea9c94b5d46d9cec05dbfff1..945f7e46e142d3af2dada06431cedb5fefecc93b 100644 --- a/llvm/include/llvm/IR/Operator.h +++ b/llvm/include/llvm/IR/Operator.h @@ -568,6 +568,11 @@ public: bool accumulateConstantOffset( const DataLayout &DL, APInt &Offset, function_ref ExternalAnalysis = nullptr) const; + + static bool accumulateConstantOffset( + Type *SourceType, ArrayRef Index, const DataLayout &DL, + APInt &Offset, + function_ref ExternalAnalysis = nullptr); }; class PtrToIntOperator diff --git a/llvm/include/llvm/IR/PseudoProbe.h b/llvm/include/llvm/IR/PseudoProbe.h index e0370c264102348c7707c16346e0f637e44933a2..5165e80caa2d381cd080229bf10814ddd54a9659 100644 --- a/llvm/include/llvm/IR/PseudoProbe.h +++ b/llvm/include/llvm/IR/PseudoProbe.h @@ -16,28 +16,39 @@ #include "llvm/ADT/Optional.h" #include #include +#include namespace llvm { class Instruction; +class BasicBlock; constexpr const char *PseudoProbeDescMetadataName = "llvm.pseudo_probe_desc"; enum class PseudoProbeType { Block = 0, IndirectCall, DirectCall }; +// The saturated distrution factor representing 100% for block probes. +constexpr static uint64_t PseudoProbeFullDistributionFactor = + std::numeric_limits::max(); + struct PseudoProbeDwarfDiscriminator { +public: // The following APIs encodes/decodes per-probe information to/from a // 32-bit integer which is organized as: // [2:0] - 0x7, this is reserved for regular discriminator, // see DWARF discriminator encoding rule // [18:3] - probe id - // [25:19] - reserved + // [25:19] - probe distribution factor // [28:26] - probe type, see PseudoProbeType // [31:29] - reserved for probe attributes - static uint32_t packProbeData(uint32_t Index, uint32_t Type) { + static uint32_t packProbeData(uint32_t Index, uint32_t Type, uint32_t Flags, + uint32_t Factor) { assert(Index <= 0xFFFF && "Probe index too big to encode, exceeding 2^16"); assert(Type <= 0x7 && "Probe type too big to encode, exceeding 7"); - return (Index << 3) | (Type << 26) | 0x7; + assert(Flags <= 0x7); + assert(Factor <= 100 && + "Probe distribution factor too big to encode, exceeding 100"); + return (Index << 3) | (Factor << 19) | (Type << 26) | 0x7; } static uint32_t extractProbeIndex(uint32_t Value) { @@ -51,16 +62,26 @@ struct PseudoProbeDwarfDiscriminator { static uint32_t extractProbeAttributes(uint32_t Value) { return (Value >> 29) & 0x7; } + + static uint32_t extractProbeFactor(uint32_t Value) { + return (Value >> 19) & 0x7F; + } + + // The saturated distrution factor representing 100% for callsites. + constexpr static uint8_t FullDistributionFactor = 100; }; struct PseudoProbe { uint32_t Id; uint32_t Type; uint32_t Attr; + float Factor; }; Optional extractProbe(const Instruction &Inst); +void setProbeDistributionFactor(Instruction &Inst, float Factor); + } // end namespace llvm #endif // LLVM_IR_PSEUDOPROBE_H diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h index 795a980878e2689419267a9eba19469ae07df44b..61c86b0468f221ee92a8ceb1178282b88a6b46d1 100644 --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -22,6 +22,7 @@ #include "llvm/IR/PassTimingInfo.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/IPO/SampleProfileProbe.h" #include #include @@ -273,6 +274,7 @@ class StandardInstrumentations { OptBisectInstrumentation OptBisect; PreservedCFGCheckerInstrumentation PreservedCFGChecker; IRChangedPrinter PrintChangedIR; + PseudoProbeVerifier PseudoProbeVerification; VerifyInstrumentation Verify; bool VerifyEach; diff --git a/llvm/include/llvm/ProfileData/ProfileCommon.h b/llvm/include/llvm/ProfileData/ProfileCommon.h index 6bb5825339ae145b10add71846420801ddb505ed..55b94b2e690de853fa13436e93bdcd53642ac19d 100644 --- a/llvm/include/llvm/ProfileData/ProfileCommon.h +++ b/llvm/include/llvm/ProfileData/ProfileCommon.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Error.h" #include #include @@ -89,6 +90,8 @@ public: void addRecord(const sampleprof::FunctionSamples &FS, bool isCallsiteSample = false); + std::unique_ptr computeSummaryForProfiles( + const StringMap &Profiles); std::unique_ptr getSummary(); }; diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index c45ace9e68c16287bbe9dd4486e62ac62e7ababa..25d5b2376c114329ae4fec1f024e0a3c6704f92f 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -347,6 +347,16 @@ public: return SortedTargets; } + /// Prorate call targets by a distribution factor. + static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets, + float DistributionFactor) { + CallTargetMap AdjustedTargets; + for (const auto &I : Targets) { + AdjustedTargets[I.first()] = I.second * DistributionFactor; + } + return AdjustedTargets; + } + /// Merge the samples in \p Other into this record. /// Optionally scale sample counts by \p Weight. sampleprof_error merge(const SampleRecord &Other, uint64_t Weight = 1) { @@ -439,9 +449,11 @@ public: void clearState(ContextStateMask S) { State &= (uint32_t)~S; } bool hasContext() const { return State != UnknownContext; } bool isBaseContext() const { return CallingContext.empty(); } - StringRef getName() const { return Name; } + StringRef getNameWithoutContext() const { return Name; } StringRef getCallingContext() const { return CallingContext; } - StringRef getNameWithContext() const { return FullContext; } + StringRef getNameWithContext(bool WithBracket = false) const { + return WithBracket ? InputContext : FullContext; + } private: // Give a context string, decode and populate internal states like @@ -449,6 +461,7 @@ private: // `ContextStr`: `[main:3 @ _Z5funcAi:1 @ _Z8funcLeafi]` void setContext(StringRef ContextStr, ContextStateMask CState) { assert(!ContextStr.empty()); + InputContext = ContextStr; // Note that `[]` wrapped input indicates a full context string, otherwise // it's treated as context-less function name only. bool HasContext = ContextStr.startswith("["); @@ -480,6 +493,9 @@ private: } } + // Input context string including bracketed calling context and leaf function + // name + StringRef InputContext; // Full context string including calling context and leaf function name StringRef FullContext; // Function name for the associated sample profile @@ -676,7 +692,8 @@ public: Name = Other.getName(); if (!GUIDToFuncNameMap) GUIDToFuncNameMap = Other.GUIDToFuncNameMap; - + if (Context.getNameWithContext(true).empty()) + Context = Other.getContext(); if (FunctionHash == 0) { // Set the function hash code for the target profile. FunctionHash = Other.getFunctionHash(); @@ -743,8 +760,10 @@ public: StringRef getName() const { return Name; } /// Return function name with context. - StringRef getNameWithContext() const { - return FunctionSamples::ProfileIsCS ? Context.getNameWithContext() : Name; + StringRef getNameWithContext(bool WithBracket = false) const { + return FunctionSamples::ProfileIsCS + ? Context.getNameWithContext(WithBracket) + : Name; } /// Return the original function name. diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h index 3f52a2f6163b7110b55935317507aa5806238366..999e75eddffac263c7bfbd253eefca3241180826 100644 --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -488,8 +488,12 @@ protected: /// \brief Whether samples are collected based on pseudo probes. bool ProfileIsProbeBased = false; + /// Whether function profiles are context-sensitive. bool ProfileIsCS = false; + /// Number of context-sensitive profiles. + uint32_t CSProfileCount = 0; + /// \brief The format of sample. SampleProfileFormat Format = SPF_None; }; diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h index 38f3e188be553bdcdfd0440edc99b688529f9752..0706aa226c0e3e4065f32e7aabb2df85467f0c7a 100644 --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -369,9 +369,22 @@ public: virtual void setDefault() = 0; + // Prints the help string for an option. + // + // This maintains the Indent for multi-line descriptions. + // FirstLineIndentedBy is the count of chars of the first line + // i.e. the one containing the --