diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 37aea5f6657f01f9b3da1a81bedf3103ad8bddd1..45da8af51bb9cefa6312b8966bf6cd63a6dcc09e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -119,6 +119,10 @@ clang/test/AST/Interp/ @tbaederr /mlir/test/python/ @ftynse @makslevental @stellaraccident /mlir/python/ @ftynse @makslevental @stellaraccident +# MLIR Mem2Reg/SROA +/mlir/**/Transforms/Mem2Reg.* @moxinilian +/mlir/**/Transforms/SROA.* @moxinilian + # BOLT /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml index 1e9367732e591118445fef2c69acf3339c2cbf5d..44a3d79c72c0ac9b80598d946d93f9af110f9df3 100644 --- a/.github/workflows/libcxx-build-and-test.yaml +++ b/.github/workflows/libcxx-build-and-test.yaml @@ -61,12 +61,10 @@ jobs: ] cc: [ 'clang-19' ] cxx: [ 'clang++-19' ] - clang_tidy: [ 'ON' ] include: - config: 'generic-gcc' cc: 'gcc-13' cxx: 'g++-13' - clang_tidy: 'OFF' steps: - uses: actions/checkout@v4 - name: ${{ matrix.config }}.${{ matrix.cxx }} @@ -74,7 +72,6 @@ jobs: env: CC: ${{ matrix.cc }} CXX: ${{ matrix.cxx }} - ENABLE_CLANG_TIDY: ${{ matrix.clang_tidy }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 if: always() with: @@ -102,20 +99,16 @@ jobs: ] cc: [ 'clang-19' ] cxx: [ 'clang++-19' ] - clang_tidy: [ 'ON' ] include: - config: 'generic-gcc-cxx11' cc: 'gcc-13' cxx: 'g++-13' - clang_tidy: 'OFF' - config: 'generic-cxx23' cc: 'clang-17' cxx: 'clang++-17' - clang_tidy: 'OFF' - config: 'generic-cxx26' cc: 'clang-18' cxx: 'clang++-18' - clang_tidy: 'ON' steps: - uses: actions/checkout@v4 - name: ${{ matrix.config }} @@ -123,7 +116,6 @@ jobs: env: CC: ${{ matrix.cc }} CXX: ${{ matrix.cxx }} - ENABLE_CLANG_TIDY: ${{ matrix.clang_tidy }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 if: always() # Upload artifacts even if the build or test suite fails with: @@ -188,7 +180,6 @@ jobs: env: CC: clang-19 CXX: clang++-19 - ENABLE_CLANG_TIDY: "OFF" - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 if: always() with: diff --git a/bolt/test/AArch64/constant_island_pie_update.s b/bolt/test/AArch64/constant_island_pie_update.s index 0ab67d07a854ec49da550bfd0aa882c875a672b1..313e103b19c05a85e0ad0d8bb898d0d935d5b8b5 100644 --- a/bolt/test/AArch64/constant_island_pie_update.s +++ b/bolt/test/AArch64/constant_island_pie_update.s @@ -18,7 +18,7 @@ # RUN: llvm-objdump -j .text -d --show-all-symbols %t.relr.bolt | FileCheck %s # RUN: llvm-objdump -j .text -d %t.relr.bolt | \ # RUN: FileCheck %s --check-prefix=ADDENDCHECK -# RUN: llvm-readelf -rsW %t.relr.bolt | FileCheck --check-prefix=ELFCHECK %s +# RUN: llvm-readelf -rsW %t.relr.bolt | FileCheck --check-prefix=RELRELFCHECK %s # RUN: llvm-readelf -SW %t.relr.bolt | FileCheck --check-prefix=RELRSZCHECK %s // Check that the CI value was updated @@ -51,6 +51,12 @@ # ELFCHECK-NEXT: {{.*}} R_AARCH64_RELATIVE # ELFCHECK: {{.*}}[[#OFF]] {{.*}} $d +# RELRELFCHECK: $d{{$}} +# RELRELFCHECK-NEXT: $d + 0x8{{$}} +# RELRELFCHECK-NEXT: $d + 0x18{{$}} +# RELRELFCHECK-NEXT: mytextP +# RELRELFCHECK-EMPTY: + // Check that .relr.dyn size is 2 bytes to ensure that last 3 relocations were // encoded as a bitmap so the total section size for 3 relocations is 2 bytes. # RELRSZCHECK: .relr.dyn RELR [[#%x,ADDR:]] [[#%x,OFF:]] {{0*}}10 diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 84233c36e15d989f8aca8a1023377e5566c6464b..2afff2929cf79c2bda5d40c26951f49d47c788f3 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -380,8 +380,8 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx, this->SourceRoot = std::string(SourceRootDir); if (!RepositoryUrl.empty()) { this->RepositoryUrl = std::string(RepositoryUrl); - if (!RepositoryUrl.empty() && RepositoryUrl.find("http://") != 0 && - RepositoryUrl.find("https://") != 0) + if (!RepositoryUrl.empty() && !RepositoryUrl.starts_with("http://") && + !RepositoryUrl.starts_with("https://")) this->RepositoryUrl->insert(0, "https://"); } } diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp index 3e926236adb4517245475d2f7b5f420268373e1a..710b361e16c0a717b562fa32aee9f332032430cb 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -139,6 +139,12 @@ void ClangTidyCheck::OptionsView::storeInt(ClangTidyOptions::OptionMap &Options, store(Options, LocalName, llvm::itostr(Value)); } +void ClangTidyCheck::OptionsView::storeUnsigned( + ClangTidyOptions::OptionMap &Options, StringRef LocalName, + uint64_t Value) const { + store(Options, LocalName, llvm::utostr(Value)); +} + template <> void ClangTidyCheck::OptionsView::store( ClangTidyOptions::OptionMap &Options, StringRef LocalName, diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h index 656a2f008f6e0e52a168e9f29bbc5d36fcf11d33..7427aa9bf48f89367bf81a2fb2af65e4a449876c 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h @@ -411,7 +411,10 @@ public: std::enable_if_t> store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) const { - storeInt(Options, LocalName, Value); + if constexpr (std::is_signed_v) + storeInt(Options, LocalName, Value); + else + storeUnsigned(Options, LocalName, Value); } /// Stores an option with the check-local name \p LocalName with @@ -422,7 +425,7 @@ public: store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, std::optional Value) const { if (Value) - storeInt(Options, LocalName, *Value); + store(Options, LocalName, *Value); else store(Options, LocalName, "none"); } @@ -470,6 +473,8 @@ public: void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, int64_t Value) const; + void storeUnsigned(ClangTidyOptions::OptionMap &Options, + StringRef LocalName, uint64_t Value) const; std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; diff --git a/clang-tools-extra/clang-tidy/GlobList.cpp b/clang-tools-extra/clang-tidy/GlobList.cpp index dfe3f7c505b1747126de68ea3075999c3b1ff4f6..8f09ee075bbd6e854301fbefa01e65693604bd55 100644 --- a/clang-tools-extra/clang-tidy/GlobList.cpp +++ b/clang-tools-extra/clang-tidy/GlobList.cpp @@ -19,12 +19,17 @@ static bool consumeNegativeIndicator(StringRef &GlobList) { return GlobList.consume_front("-"); } -// Converts first glob from the comma-separated list of globs to Regex and -// removes it and the trailing comma from the GlobList. -static llvm::Regex consumeGlob(StringRef &GlobList) { +// Extracts the first glob from the comma-separated list of globs, +// removes it and the trailing comma from the GlobList and +// returns the extracted glob. +static llvm::StringRef extractNextGlob(StringRef &GlobList) { StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find_first_of(",\n")); StringRef Glob = UntrimmedGlob.trim(); GlobList = GlobList.substr(UntrimmedGlob.size() + 1); + return Glob; +} + +static llvm::Regex createRegexFromGlob(StringRef &Glob) { SmallString<128> RegexText("^"); StringRef MetaChars("()^$|*+?.[]\\{}"); for (char C : Glob) { @@ -43,7 +48,8 @@ GlobList::GlobList(StringRef Globs, bool KeepNegativeGlobs /* =true */) { do { GlobListItem Item; Item.IsPositive = !consumeNegativeIndicator(Globs); - Item.Regex = consumeGlob(Globs); + Item.Text = extractNextGlob(Globs); + Item.Regex = createRegexFromGlob(Item.Text); if (Item.IsPositive || KeepNegativeGlobs) Items.push_back(std::move(Item)); } while (!Globs.empty()); diff --git a/clang-tools-extra/clang-tidy/GlobList.h b/clang-tools-extra/clang-tidy/GlobList.h index 44af182e43b0024c16153d20c757f84795c67b13..4317928270adff9496579f934be576b990a03565 100644 --- a/clang-tools-extra/clang-tidy/GlobList.h +++ b/clang-tools-extra/clang-tidy/GlobList.h @@ -44,8 +44,12 @@ private: struct GlobListItem { bool IsPositive; llvm::Regex Regex; + llvm::StringRef Text; }; SmallVector Items; + +public: + const SmallVectorImpl &getItems() const { return Items; }; }; /// A \p GlobList that caches search results, so that search is performed only diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp index 5260a8b4ecb0bad3358ddb2bbc519a5be82ad26d..32f5edddfe80b158d96df4fa569ee59dfe0ad210 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp @@ -8,7 +8,9 @@ #include "LambdaFunctionNameCheck.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" @@ -56,6 +58,8 @@ private: LambdaFunctionNameCheck::SourceRangeSet* SuppressMacroExpansions; }; +AST_MATCHER(CXXMethodDecl, isInLambda) { return Node.getParent()->isLambda(); } + } // namespace LambdaFunctionNameCheck::LambdaFunctionNameCheck(StringRef Name, @@ -69,9 +73,13 @@ void LambdaFunctionNameCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) { - // Match on PredefinedExprs inside a lambda. - Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"), - this); + Finder->addMatcher( + cxxMethodDecl(isInLambda(), + hasBody(forEachDescendant( + predefinedExpr(hasAncestor(cxxMethodDecl().bind("fn"))) + .bind("E"))), + equalsBoundNode("fn")), + this); } void LambdaFunctionNameCheck::registerPPCallbacks( diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index 9f3d6b6db6cbca1b0cc9aa3b7c71b4746f34d712..f82f4417141d3df287dfafb5182715aa09be7352 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -454,52 +454,27 @@ static constexpr StringLiteral VerifyConfigWarningEnd = " [-verify-config]\n"; static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob, StringRef Source) { - llvm::StringRef Cur, Rest; + GlobList Globs(CheckGlob); bool AnyInvalid = false; - for (std::tie(Cur, Rest) = CheckGlob.split(','); - !(Cur.empty() && Rest.empty()); std::tie(Cur, Rest) = Rest.split(',')) { - Cur = Cur.trim(); - if (Cur.empty()) + for (const auto &Item : Globs.getItems()) { + if (Item.Text.starts_with("clang-diagnostic")) continue; - Cur.consume_front("-"); - if (Cur.starts_with("clang-diagnostic")) - continue; - if (Cur.contains('*')) { - SmallString<128> RegexText("^"); - StringRef MetaChars("()^$|*+?.[]\\{}"); - for (char C : Cur) { - if (C == '*') - RegexText.push_back('.'); - else if (MetaChars.contains(C)) - RegexText.push_back('\\'); - RegexText.push_back(C); - } - RegexText.push_back('$'); - llvm::Regex Glob(RegexText); - std::string Error; - if (!Glob.isValid(Error)) { - AnyInvalid = true; - llvm::WithColor::error(llvm::errs(), Source) - << "building check glob '" << Cur << "' " << Error << "'\n"; - continue; - } - if (llvm::none_of(AllChecks.keys(), - [&Glob](StringRef S) { return Glob.match(S); })) { - AnyInvalid = true; + if (llvm::none_of(AllChecks.keys(), + [&Item](StringRef S) { return Item.Regex.match(S); })) { + AnyInvalid = true; + if (Item.Text.contains('*')) llvm::WithColor::warning(llvm::errs(), Source) - << "check glob '" << Cur << "' doesn't match any known check" + << "check glob '" << Item.Text << "' doesn't match any known check" << VerifyConfigWarningEnd; + else { + llvm::raw_ostream &Output = + llvm::WithColor::warning(llvm::errs(), Source) + << "unknown check '" << Item.Text << '\''; + llvm::StringRef Closest = closest(Item.Text, AllChecks); + if (!Closest.empty()) + Output << "; did you mean '" << Closest << '\''; + Output << VerifyConfigWarningEnd; } - } else { - if (AllChecks.contains(Cur)) - continue; - AnyInvalid = true; - llvm::raw_ostream &Output = llvm::WithColor::warning(llvm::errs(), Source) - << "unknown check '" << Cur << '\''; - llvm::StringRef Closest = closest(Cur, AllChecks); - if (!Closest.empty()) - Output << "; did you mean '" << Closest << '\''; - Output << VerifyConfigWarningEnd; } } return AnyInvalid; diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 0af6036734ba53b49cb8772f508f9415a8aed04f..799a549ff0816e388cb6acdda5e04d1ddb7f38b4 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -427,7 +427,7 @@ TEST_F(TargetDeclTest, Types) { [[auto]] X = S{}; )cpp"; // FIXME: deduced type missing in AST. https://llvm.org/PR42914 - EXPECT_DECLS("AutoTypeLoc"); + EXPECT_DECLS("AutoTypeLoc", ); Code = R"cpp( template @@ -727,13 +727,13 @@ TEST_F(TargetDeclTest, BuiltinTemplates) { template using make_integer_sequence = [[__make_integer_seq]]; )cpp"; - EXPECT_DECLS("TemplateSpecializationTypeLoc"); + EXPECT_DECLS("TemplateSpecializationTypeLoc", ); Code = R"cpp( template using type_pack_element = [[__type_pack_element]]; )cpp"; - EXPECT_DECLS("TemplateSpecializationTypeLoc"); + EXPECT_DECLS("TemplateSpecializationTypeLoc", ); } TEST_F(TargetDeclTest, MemberOfTemplate) { @@ -1018,7 +1018,7 @@ TEST_F(TargetDeclTest, DependentTypes) { typedef typename waldo::type::[[next]] type; }; )cpp"; - EXPECT_DECLS("DependentNameTypeLoc"); + EXPECT_DECLS("DependentNameTypeLoc", ); // Similar to above but using mutually recursive templates. Code = R"cpp( @@ -1035,7 +1035,7 @@ TEST_F(TargetDeclTest, DependentTypes) { using type = typename even::type::[[next]]; }; )cpp"; - EXPECT_DECLS("DependentNameTypeLoc"); + EXPECT_DECLS("DependentNameTypeLoc", ); } TEST_F(TargetDeclTest, TypedefCascade) { @@ -1263,14 +1263,14 @@ TEST_F(TargetDeclTest, ObjC) { + ([[id]])sharedInstance; @end )cpp"; - EXPECT_DECLS("TypedefTypeLoc"); + EXPECT_DECLS("TypedefTypeLoc", ); Code = R"cpp( @interface Foo + ([[instancetype]])sharedInstance; @end )cpp"; - EXPECT_DECLS("TypedefTypeLoc"); + EXPECT_DECLS("TypedefTypeLoc", ); } class FindExplicitReferencesTest : public ::testing::Test { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a457e6fcae946256ee907b33a206542f29f1c055..28840b9beae881865b8836b855f737880f91f70a 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -102,6 +102,11 @@ Improvements to clang-tidy similar fashion to what `-header-filter` does for header files. - Improved :program:`check_clang_tidy.py` script. Added argument `-export-fixes` to aid in clang-tidy and test development. +- Fixed bug where big values for unsigned check options overflowed into negative values + when being printed with ``--dump-config``. + +- Fixed ``--verify-config`` option not properly parsing checks when using the + literal operator in the ``.clang-tidy`` config. New checks ^^^^^^^^^^ @@ -155,6 +160,10 @@ Changes in existing checks ` check to ignore code within unevaluated contexts, such as ``decltype``. +- Improved :doc:`bugprone-lambda-function-name` + check by ignoring ``__func__`` macro in lambda captures, initializers of + default parameters and nested function declarations. + - Improved :doc:`bugprone-non-zero-enum-to-bool-conversion ` check by eliminating false positives resulting from direct usage of bitwise operators diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 8bc46acad56c8416ba8fad3bf592be0fc021e20e..3a06d7c30c9b79e647e2525a67577acf84121345 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -341,9 +341,9 @@ Clang-Tidy Checks :doc:`portability-std-allocator-const `, :doc:`readability-avoid-const-params-in-decls `, "Yes" :doc:`readability-avoid-nested-conditional-operator `, - :doc:`readability-avoid-return-with-void-value `, + :doc:`readability-avoid-return-with-void-value `, "Yes" :doc:`readability-avoid-unconditional-preprocessor-if `, - :doc:`readability-braces-around-statements `, "Yes" + :doc:`readability-braces-around-statements `, :doc:`readability-const-return-type `, "Yes" :doc:`readability-container-contains `, "Yes" :doc:`readability-container-data-pointer `, "Yes" @@ -529,12 +529,12 @@ Clang-Tidy Checks :doc:`cppcoreguidelines-non-private-member-variables-in-classes `, :doc:`misc-non-private-member-variables-in-classes `, :doc:`cppcoreguidelines-use-default-member-init `, :doc:`modernize-use-default-member-init `, "Yes" :doc:`fuchsia-header-anon-namespaces `, :doc:`google-build-namespaces `, - :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" + :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, :doc:`google-readability-function-size `, :doc:`readability-function-size `, :doc:`google-readability-namespace-comments `, :doc:`llvm-namespace-comment `, :doc:`hicpp-avoid-c-arrays `, :doc:`modernize-avoid-c-arrays `, :doc:`hicpp-avoid-goto `, :doc:`cppcoreguidelines-avoid-goto `, - :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" + :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, :doc:`hicpp-deprecated-headers `, :doc:`modernize-deprecated-headers `, "Yes" :doc:`hicpp-explicit-conversions `, :doc:`google-explicit-constructor `, "Yes" :doc:`hicpp-function-size `, :doc:`readability-function-size `, diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp index 936ee87a856cd2ff0c36856e81178be3ea916cfa..5c2bb5713239ce1b8a1d9117cf48d1f1e528667a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp @@ -19,6 +19,22 @@ void Positives() { // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] [] { EMBED_IN_ANOTHER_MACRO1; }(); // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + [] { + __func__; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + struct S { + void f() { + __func__; + [] { + __func__; + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + }(); + __func__; + } + }; + __func__; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + }(); } #define FUNC_MACRO_WITH_FILE_AND_LINE Foo(__func__, __FILE__, __LINE__) @@ -40,4 +56,7 @@ void Negatives() { [] { FUNC_MACRO_WITH_FILE_AND_LINE; }(); [] { FUNCTION_MACRO_WITH_FILE_AND_LINE; }(); [] { EMBED_IN_ANOTHER_MACRO2; }(); + + [] (const char* func = __func__) { func; }(); + [func=__func__] { func; }(); } diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/5/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/5/.clang-tidy new file mode 100644 index 0000000000000000000000000000000000000000..e33f0f8bb33218a505055f5be62422aa3f1624a5 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/5/.clang-tidy @@ -0,0 +1,4 @@ +InheritParentConfig: true +Checks: 'misc-throw-by-value-catch-by-reference' +CheckOptions: + misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976' diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp index ab4f3becb7a9fc5633b58716a28b517f9660967e..cb0f0bc4d133085e71d01dd9b96032f75166f887 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp @@ -64,3 +64,11 @@ // Validate that check options are printed in alphabetical order: // RUN: clang-tidy --checks="-*,readability-identifier-naming" --dump-config %S/Inputs/config-files/- -- | grep "readability-identifier-naming\." | sort --check + +// Dumped config does not overflow for unsigned options +// RUN: clang-tidy --dump-config \ +// RUN: --checks="-*,misc-throw-by-value-catch-by-reference" \ +// RUN: -- | grep -v -q "misc-throw-by-value-catch-by-reference.MaxSize: '-1'" + +// RUN: clang-tidy --dump-config %S/Inputs/config-files/5/- \ +// RUN: -- | grep -q "misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976'" diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp index 421f8641281acb2772c657bdf876acb507a7a7ad..3659285986482a998b02f6c593c71564faa7bd3c 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp @@ -18,3 +18,15 @@ // CHECK-VERIFY: command-line option '-checks': warning: check glob 'bad*glob' doesn't match any known check [-verify-config] // CHECK-VERIFY: command-line option '-checks': warning: unknown check 'llvm-includeorder'; did you mean 'llvm-include-order' [-verify-config] // CHECK-VERIFY: command-line option '-checks': warning: unknown check 'my-made-up-check' [-verify-config] + +// RUN: echo -e 'Checks: |\n bugprone-argument-comment\n bugprone-assert-side-effect,\n bugprone-bool-pointer-implicit-conversion\n readability-use-anyof*' > %T/MyClangTidyConfig +// RUN: clang-tidy -verify-config \ +// RUN: --config-file=%T/MyClangTidyConfig | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-OK +// CHECK-VERIFY-BLOCK-OK: No config errors detected. + +// RUN: echo -e 'Checks: |\n bugprone-arguments-*\n bugprone-assert-side-effects\n bugprone-bool-pointer-implicit-conversion' > %T/MyClangTidyConfigBad +// RUN: not clang-tidy -verify-config \ +// RUN: --config-file=%T/MyClangTidyConfigBad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-BAD +// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: check glob 'bugprone-arguments-*' doesn't match any known check [-verify-config] +// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: unknown check 'bugprone-assert-side-effects'; did you mean 'bugprone-assert-side-effect' [-verify-config] + diff --git a/clang/cmake/caches/Apple-stage2.cmake b/clang/cmake/caches/Apple-stage2.cmake index ede256a2da6b8fd6864bd8584aeddf5126dd5bb9..e919c56739679ebc5e8193e8a1f06e65fc4b1376 100644 --- a/clang/cmake/caches/Apple-stage2.cmake +++ b/clang/cmake/caches/Apple-stage2.cmake @@ -16,6 +16,7 @@ set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") set(LLVM_ENABLE_MODULES ON CACHE BOOL "") set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "") set(LLVM_ENABLE_EXPORTED_SYMBOLS_IN_EXECUTABLES OFF CACHE BOOL "") +set(LLVM_PLUGIN_SUPPORT OFF CACHE BOOL "") set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") set(CLANG_SPAWN_CC1 ON CACHE BOOL "") set(BUG_REPORT_URL "http://developer.apple.com/bugreporter/" CACHE STRING "") diff --git a/clang/docs/ClangOffloadBundler.rst b/clang/docs/ClangOffloadBundler.rst index 1f8c85a08f8c79c46b9dc375d9ec167d80a78346..515e6c00a3b8003083508e562812317338314206 100644 --- a/clang/docs/ClangOffloadBundler.rst +++ b/clang/docs/ClangOffloadBundler.rst @@ -518,11 +518,14 @@ The compressed offload bundle begins with a header followed by the compressed bi This is a unique identifier to distinguish compressed offload bundles. The value is the string 'CCOB' (Compressed Clang Offload Bundle). - **Version Number (16-bit unsigned int)**: - This denotes the version of the compressed offload bundle format. The current version is `1`. + This denotes the version of the compressed offload bundle format. The current version is `2`. - **Compression Method (16-bit unsigned int)**: This field indicates the compression method used. The value corresponds to either `zlib` or `zstd`, represented as a 16-bit unsigned integer cast from the LLVM compression enumeration. +- **Total File Size (32-bit unsigned int)**: + This is the total size (in bytes) of the file, including the header. Available in version 2 and above. + - **Uncompressed Binary Size (32-bit unsigned int)**: This is the size (in bytes) of the binary data before it was compressed. diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 3bead159c8f9467dd876174beff98787eb6a890b..84fc4dee02fa803766b66528e53f40057fc8a1df 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1642,7 +1642,8 @@ The following type trait primitives are supported by Clang. Those traits marked were made trivially relocatable via the ``clang::trivial_abi`` attribute. * ``__is_trivially_equality_comparable`` (Clang): Returns true if comparing two objects of the provided type is known to be equivalent to comparing their - value representations. + object representations. Note that types containing padding bytes are never + trivially equality comparable. * ``__is_unbounded_array`` (C++, GNU, Microsoft, Embarcadero) * ``__is_union`` (C++, GNU, Microsoft, Embarcadero) * ``__is_unsigned`` (C++, Embarcadero): diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 193bbd6b1a4702c879f8a07ee331210ca20506c3..d1f7293a842bb684c1f881d0fb60f4926a191716 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -88,6 +88,7 @@ sections with improvements to Clang's support for those languages. C++ Language Changes -------------------- +- Implemented ``_BitInt`` literal suffixes ``__wb`` or ``__WB`` as a Clang extension with ``unsigned`` modifiers also allowed. (#GH85223). C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -179,6 +180,9 @@ C23 Feature Support - Clang now supports `N3018 The constexpr specifier for object definitions` `_. +- Properly promote bit-fields of bit-precise integer types to the field's type + rather than to ``int``. #GH87641 + Non-comprehensive list of changes in this release ------------------------------------------------- @@ -248,6 +252,8 @@ Modified Compiler Flags f3 *c = (f3 *)x; } +- Carved out ``-Wformat`` warning about scoped enums into a subwarning and + make it controlled by ``-Wformat-pedantic``. Fixes #GH88595. Removed Compiler Flags ------------------------- @@ -538,6 +544,8 @@ Bug Fixes to C++ Support - Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). - Fixed a bug that prevented member function templates of class templates declared with a deduced return type from being explicitly specialized for a given implicit instantiation of the class template. +- Fixed a crash when ``this`` is used in a dependent class scope function template specialization + that instantiates to a static member function. - Fix crash when inheriting from a cv-qualified type. Fixes #GH35603 - Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790). @@ -549,6 +557,11 @@ Bug Fixes to C++ Support - Fix a crash in requires expression with templated base class member function. Fixes (#GH84020). - Fix a crash caused by defined struct in a type alias template when the structure has fields with dependent type. Fixes (#GH75221). +- Fix placement new initializes typedef array with correct size. Fixes (#GH41441). +- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906) +- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()`` + function returns a large or negative value. Fixes (#GH89407). +- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -558,6 +571,9 @@ Bug Fixes to AST Handling Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed an infinite recursion in ASTImporter, on return type declared inside + body of C++11 lambda without trailing return (#GH68775). + Miscellaneous Clang Crashes Fixed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -645,6 +661,12 @@ CUDA Support AIX Support ^^^^^^^^^^^ +- Introduced the ``-maix-small-local-dynamic-tls`` option to produce a faster + access sequence for local-dynamic TLS variables where the offset from the TLS + base is encoded as an immediate operand. + This access sequence is not used for TLS variables larger than 32KB, and is + currently only supported on 64-bit mode. + WebAssembly Support ^^^^^^^^^^^^^^^^^^^ @@ -695,6 +717,8 @@ Static Analyzer - Support C++23 static operator calls. (#GH84972) - Fixed a crash in ``security.cert.env.InvalidPtr`` checker when accidentally matched user-defined ``strerror`` and similar library functions. (GH#88181) +- Fixed a crash when storing through an address that refers to the address of + a label. (GH#89185) New features ^^^^^^^^^^^^ diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index c464bc3a69adc51c1f59db5245f1fc077aed4a11..8df40566fcba3d815a8a4e18da81e4e708580269 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -4921,6 +4921,9 @@ directory. Using the example installation above, this would mean passing If the user links the program with the ``clang`` or ``clang-cl`` drivers, the driver will pass this flag for them. +The auto-linking can be disabled with -fno-rtlib-defaultlib. If that flag is +used, pass the complete flag to required libraries as described for ASan below. + If the linker cannot find the appropriate library, it will emit an error like this:: diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 28f8d67811f0a2517fba976008f0849b4793f25a..d5ed20ff50157d611ba643c9bdf6e2a5302a68de 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -455,7 +455,7 @@ class ASTContext : public RefCountedBase { /// initialization of another module). struct PerModuleInitializers { llvm::SmallVector Initializers; - llvm::SmallVector LazyInitializers; + llvm::SmallVector LazyInitializers; void resolve(ASTContext &Ctx); }; @@ -1059,7 +1059,7 @@ public: /// or an ImportDecl nominating another module that has initializers. void addModuleInitializer(Module *M, Decl *Init); - void addLazyModuleInitializers(Module *M, ArrayRef IDs); + void addLazyModuleInitializers(Module *M, ArrayRef IDs); /// Get the initializations to perform when importing a module, if any. ArrayRef getModuleInitializers(Module *M); diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index f5c47d8a7c2113ab5e3303fda5e86dbb27f029d2..216dc9eef08b62c87cde4d19d5af36c2f2680562 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -851,6 +851,12 @@ public: Visit(R); } + void VisitTypeTraitExpr(const TypeTraitExpr *E) { + // Argument types are not children of the TypeTraitExpr. + for (auto *A : E->getArgs()) + Visit(A->getType()); + } + void VisitLambdaExpr(const LambdaExpr *Node) { if (Traversal == TK_IgnoreUnlessSpelledInSource) { for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 161e14fc896922fbacbd018df904a70b8c0b793b..d8cafc3d81526ef53ac6290fc6f03cae2acdf6f3 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -239,6 +239,9 @@ public: ModulePrivate }; + /// An ID number that refers to a declaration in an AST file. + using DeclID = uint32_t; + protected: /// The next declaration within the same lexical /// DeclContext. These pointers form the linked list that is @@ -349,8 +352,6 @@ protected: LLVM_PREFERRED_TYPE(Linkage) mutable unsigned CacheValidAndLinkage : 3; - using DeclID = uint32_t; - /// Allocate memory for a deserialized declaration. /// /// This routine must be used to allocate memory for any declaration that is @@ -778,9 +779,9 @@ public: /// Retrieve the global declaration ID associated with this /// declaration, which specifies where this Decl was loaded from. - unsigned getGlobalID() const { + DeclID getGlobalID() const { if (isFromASTFile()) - return *((const unsigned*)this - 1); + return *((const DeclID *)this - 1); return 0; } diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index e2afff8d445016d5dc656fb016c789b56e39add2..231bda44a9fcfdfbcfc532cb0894040dc6332492 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -797,7 +797,7 @@ protected: /// /// The first value in the array is the number of specializations/partial /// specializations that follow. - uint32_t *LazySpecializations = nullptr; + Decl::DeclID *LazySpecializations = nullptr; /// The set of "injected" template arguments used within this /// template. diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index d28e5c3a78ee4bbb9c76ddb2d229a9d99372ab19..a915745d2d7322c7bf34321d0f69b6b40fb6c4ce 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3198,7 +3198,6 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, - bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent); @@ -3218,8 +3217,9 @@ public: static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); + const DeclarationNameInfo &NameInfo, bool RequiresADL, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3240,9 +3240,6 @@ public: /// argument-dependent lookup. bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; } - /// True if this lookup is overloaded. - bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; } - /// Gets the 'naming class' (in the sense of C++0x /// [class.access.base]p5) of the lookup. This is the scope /// that was looked in to find these results. diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 230c83943c2224469f59e40d5eb264a262e453d3..eee8d6b6c6ef115e2e9c44d8aca7ee714f58ea6f 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -99,7 +99,7 @@ public: /// passes back decl sets as VisibleDeclaration objects. /// /// The default implementation of this method is a no-op. - virtual Decl *GetExternalDecl(uint32_t ID); + virtual Decl *GetExternalDecl(Decl::DeclID ID); /// Resolve a selector ID into a selector. /// @@ -579,7 +579,7 @@ using LazyDeclStmtPtr = /// A lazy pointer to a declaration. using LazyDeclPtr = - LazyOffsetPtr; + LazyOffsetPtr; /// A lazy pointer to a set of CXXCtorInitializers. using LazyCXXCtorInitializersPtr = diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 8b6d3221aa066bcc73b9a2781d614c26707e2f54..277a351c49fcb89335c19845262643986a9de157 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -156,33 +156,88 @@ public: Expr *ConditionExpr, SourceLocation EndLoc); }; -/// Represents oen of a handful of classes that have a single integer +/// Represents a clause that has one or more IntExprs. It does not own the +/// IntExprs, but provides 'children' and other accessors. +class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams { + MutableArrayRef IntExprs; + +protected: + OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {} + + /// Used only for initialization, the leaf class can initialize this to + /// trailing storage. + void setIntExprs(MutableArrayRef NewIntExprs) { + assert(IntExprs.empty() && "Cannot change IntExprs list"); + IntExprs = NewIntExprs; + } + + /// Gets the entire list of integer expressions, but leave it to the + /// individual clauses to expose this how they'd like. + llvm::ArrayRef getIntExprs() const { return IntExprs; } + +public: + child_range children() { + return child_range(reinterpret_cast(IntExprs.begin()), + reinterpret_cast(IntExprs.end())); + } + + const_child_range children() const { + child_range Children = + const_cast(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } +}; + +class OpenACCNumGangsClause final + : public OpenACCClauseWithIntExprs, + public llvm::TrailingObjects { + + OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef IntExprs, SourceLocation EndLoc) + : OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc, + LParenLoc, EndLoc) { + std::uninitialized_copy(IntExprs.begin(), IntExprs.end(), + getTrailingObjects()); + setIntExprs(MutableArrayRef(getTrailingObjects(), IntExprs.size())); + } + +public: + static OpenACCNumGangsClause * + Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef IntExprs, SourceLocation EndLoc); + + llvm::ArrayRef getIntExprs() { + return OpenACCClauseWithIntExprs::getIntExprs(); + } + + llvm::ArrayRef getIntExprs() const { + return OpenACCClauseWithIntExprs::getIntExprs(); + } +}; + +/// Represents one of a handful of clauses that have a single integer /// expression. -class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithParams { +class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs { Expr *IntExpr; protected: OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc) - : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), - IntExpr(IntExpr) {} + : OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc), + IntExpr(IntExpr) { + setIntExprs(MutableArrayRef{&this->IntExpr, 1}); + } public: - bool hasIntExpr() const { return IntExpr; } - const Expr *getIntExpr() const { return IntExpr; } - - Expr *getIntExpr() { return IntExpr; }; - - child_range children() { - return child_range(reinterpret_cast(&IntExpr), - reinterpret_cast(&IntExpr + 1)); + bool hasIntExpr() const { return !getIntExprs().empty(); } + const Expr *getIntExpr() const { + return hasIntExpr() ? getIntExprs()[0] : nullptr; } - const_child_range children() const { - return const_child_range(reinterpret_cast(&IntExpr), - reinterpret_cast(&IntExpr + 1)); - } + Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; }; }; class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr { diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 1b9c9231047717bd32f2c19d77f18264eed512bf..9cd7a364cd3f1dcd8f8c2dfddfec2017d402e57d 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1067,11 +1067,6 @@ protected: /// argument-dependent lookup if this is the operand of a function call. LLVM_PREFERRED_TYPE(bool) unsigned RequiresADL : 1; - - /// True if these lookup results are overloaded. This is pretty trivially - /// rederivable if we urgently need to kill this field. - LLVM_PREFERRED_TYPE(bool) - unsigned Overloaded : 1; }; static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4, "UnresolvedLookupExprBitfields must be <= than 4 bytes to" diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index f9fd3db1fb67fc78be3c6bfb3df55522dac68391..05748f300a932f6e6c66c8821dba70d055664dc4 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -96,6 +96,9 @@ struct ReferencedDecls { /// Returns declarations that are declared in or referenced from `FD`. ReferencedDecls getReferencedDecls(const FunctionDecl &FD); +/// Returns declarations that are declared in or referenced from `S`. +ReferencedDecls getReferencedDecls(const Stmt &S); + } // namespace dataflow } // namespace clang diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index d50dba35f8264c924d2c21ec3ac69485881fdb3a..cdf89c7def2c9185803af843f14fcbd88e59f5f5 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -244,6 +244,21 @@ public: Environment::ValueModel &Model, ExprJoinBehavior ExprBehavior); + /// Returns a value that approximates both `Val1` and `Val2`, or null if no + /// such value can be produced. + /// + /// `Env1` and `Env2` can be used to query child values and path condition + /// implications of `Val1` and `Val2` respectively. The joined value will be + /// produced in `JoinedEnv`. + /// + /// Requirements: + /// + /// `Val1` and `Val2` must model values of type `Type`. + static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1, + Value *Val2, const Environment &Env2, + Environment &JoinedEnv, + Environment::ValueModel &Model); + /// Widens the environment point-wise, using `PrevEnv` as needed to inform the /// approximation. /// diff --git a/clang/include/clang/Analysis/FlowSensitive/Transfer.h b/clang/include/clang/Analysis/FlowSensitive/Transfer.h index ed148250d8eb29ac7da1aac20bbf83bef9c15480..940025e02100f90cdfa36743daf28e2009b9ff8f 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Transfer.h +++ b/clang/include/clang/Analysis/FlowSensitive/Transfer.h @@ -53,7 +53,8 @@ private: /// Requirements: /// /// `S` must not be `ParenExpr` or `ExprWithCleanups`. -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, + Environment::ValueModel &Model); } // namespace dataflow } // namespace clang diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index dc87a8c6f022dc5f451f51f13c0dfdb068104ae6..4408d517e70e5883f1e68357a3fde364aaaf6b59 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -368,8 +368,8 @@ class Clang bit AllowInC = allowInC; } -// HLSL Semantic spellings -class HLSLSemantic : Spelling; +// HLSL Annotation spellings +class HLSLAnnotation : Spelling; class Accessor spellings> { string Name = name; @@ -4358,14 +4358,14 @@ def HLSLNumThreads: InheritableAttr { } def HLSLSV_GroupIndex: HLSLAnnotationAttr { - let Spellings = [HLSLSemantic<"SV_GroupIndex">]; + let Spellings = [HLSLAnnotation<"SV_GroupIndex">]; let Subjects = SubjectList<[ParmVar, GlobalVar]>; let LangOpts = [HLSL]; let Documentation = [HLSLSV_GroupIndexDocs]; } def HLSLResourceBinding: InheritableAttr { - let Spellings = [HLSLSemantic<"register">]; + let Spellings = [HLSLAnnotation<"register">]; let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar]>; let LangOpts = [HLSL]; let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>]; @@ -4373,7 +4373,7 @@ def HLSLResourceBinding: InheritableAttr { } def HLSLSV_DispatchThreadID: HLSLAnnotationAttr { - let Spellings = [HLSLSemantic<"SV_DispatchThreadID">]; + let Spellings = [HLSLAnnotation<"SV_DispatchThreadID">]; let Subjects = SubjectList<[ParmVar, Field]>; let LangOpts = [HLSL]; let Documentation = [HLSLSV_DispatchThreadIDDocs]; diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index ef2ddf525c981482dc9c75ded464995a513b2694..5f024b4b5fd782014c17a5e87e6b915b4732d8a9 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -52,8 +52,8 @@ public: /// Context-sensitive version of a keyword attribute. AS_ContextSensitiveKeyword, - /// : - AS_HLSLSemantic, + /// : + AS_HLSLAnnotation, /// The attibute has no source code manifestation and is only created /// implicitly. @@ -120,7 +120,7 @@ public: } static Form Pragma() { return AS_Pragma; } static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; } - static Form HLSLSemantic() { return AS_HLSLSemantic; } + static Form HLSLAnnotation() { return AS_HLSLAnnotation; } static Form Implicit() { return AS_Implicit; } private: diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index a52bf62e24202caf2746cc7c56332032c84eb214..0738f43ca555c8ecccbbf47bde2dba11afed4062 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -234,6 +234,9 @@ def err_cxx23_size_t_suffix: Error< def err_size_t_literal_too_large: Error< "%select{signed |}0'size_t' literal is out of range of possible " "%select{signed |}0'size_t' values">; +def ext_cxx_bitint_suffix : Extension< + "'_BitInt' suffix for literals is a Clang extension">, + InGroup; def ext_c23_bitint_suffix : ExtWarn< "'_BitInt' suffix for literals is a C23 extension">, InGroup; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 5251774ff4efd6d7f607431511991ca633d22252..60f87da2a7387c25fff72fefb54d5852e627e299 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1412,6 +1412,9 @@ def MultiGPU: DiagGroup<"multi-gpu">; // libc and the CRT to be skipped. def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">; +// A warning group related to AArch64 SME function attribues. +def AArch64SMEAttributes : DiagGroup<"aarch64-sme-attributes">; + // A warning group for things that will change semantics in the future. def FutureCompat : DiagGroup<"future-compat">; @@ -1517,5 +1520,8 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon // Warnings and notes InstallAPI verification. def InstallAPIViolation : DiagGroup<"installapi-violation">; +// Warnings related to _BitInt extension +def BitIntExtension : DiagGroup<"bit-int-extension">; + // Warnings about misuse of ExtractAPI options. def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 66405095d51de84ce145cb4bbb86dbca3cb16b5a..38174cf3549f14ecad83883acff62b47f15b92c0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1654,7 +1654,7 @@ def warn_ext_int_deprecated : Warning< "'_ExtInt' is deprecated; use '_BitInt' instead">, InGroup; def ext_bit_int : Extension< "'_BitInt' in %select{C17 and earlier|C++}0 is a Clang extension">, - InGroup>; + InGroup; } // end of Parse Issue category. let CategoryName = "Modules Issue" in { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a2d8bf4e4eb1513aee713118201b4257c4bd6b6..63e951daec7477679802ad24842eb33f2652c4f4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -87,9 +87,9 @@ def err_expr_not_cce : Error< "call to 'size()'|call to 'data()'}0 is not a constant expression">; def ext_cce_narrowing : ExtWarn< "%select{case value|enumerator value|non-type template argument|" - "array size|explicit specifier argument|noexcept specifier argument}0 " - "%select{cannot be narrowed from type %2 to %3|" - "evaluates to %2, which cannot be narrowed to type %3}1">, + "array size|explicit specifier argument|noexcept specifier argument|" + "call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from " + "type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">, InGroup, DefaultError, SFINAEFailure; def err_ice_not_integral : Error< "%select{integer|integral}1 constant expression must have " @@ -3754,6 +3754,16 @@ def err_sme_definition_using_za_in_non_sme_target : Error< "function using ZA state requires 'sme'">; def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; +def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning< + "passing a VL-dependent argument to/from a function that has a different" + " streaming-mode. The streaming and non-streaming vector lengths may be" + " different">, + InGroup, DefaultIgnore; +def warn_sme_locally_streaming_has_vl_args_returns : Warning< + "passing/returning a VL-dependent argument to/from a __arm_locally_streaming" + " function. The streaming and non-streaming vector" + " lengths may be different">, + InGroup, DefaultIgnore; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; def err_sme_streaming_cannot_be_multiversioned : Error< @@ -12283,4 +12293,9 @@ def note_acc_int_expr_conversion : Note<"conversion to %select{integral|enumeration}0 type %1">; def err_acc_int_expr_multiple_conversions : Error<"multiple conversions from expression type %0 to an integral type">; +def err_acc_num_gangs_num_args + : Error<"%select{no|too many}0 integer expression arguments provided to " + "OpenACC 'num_gangs' " + "%select{|clause: '%1' directive expects maximum of %2, %3 were " + "provided}0">; } // end of sema component. diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 24b109e32cdd3e95a0000411779374228a1e8477..ae4715921d166595cfe899e54527736ac9051cf7 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -224,6 +224,11 @@ public: /// - the parameter list of a template template parameter Ver17, + /// Attempt to be ABI-compatible with code generated by Clang 18.0.x. + /// This causes clang to revert some fixes to the mangling of lambdas + /// in the initializers of members of local classes. + Ver18, + /// Conform to the underlying platform's C and C++ ABIs as closely /// as we can. Latest @@ -873,6 +878,8 @@ public: /// Return difference with the given option set. FPOptionsOverride getChangesFrom(const FPOptions &Base) const; + void applyChanges(FPOptionsOverride FPO); + // We can define most of the accessors automatically: #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ TYPE get##NAME() const { \ @@ -954,6 +961,11 @@ public: setAllowFPContractAcrossStatement(); } + void setDisallowOptimizations() { + setFPPreciseEnabled(true); + setDisallowFPContract(); + } + storage_type getAsOpaqueInt() const { return (static_cast(Options.getAsOpaqueInt()) << FPOptions::StorageBitSize) | @@ -1010,6 +1022,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const return getChangesSlow(Base); } +inline void FPOptions::applyChanges(FPOptionsOverride FPO) { + *this = FPO.applyOverrides(*this); +} + /// Describes the kind of translation unit being processed. enum TranslationUnitKind { /// The translation unit is a complete translation unit. diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index 520e068f4ffd403cb523445fa8cb866dd24c9832..dd5792e7ca8c39c33492a8cc64c4cbd5d041970f 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -18,6 +18,7 @@ VISIT_CLAUSE(Default) VISIT_CLAUSE(If) VISIT_CLAUSE(Self) +VISIT_CLAUSE(NumGangs) VISIT_CLAUSE(NumWorkers) VISIT_CLAUSE(VectorLength) diff --git a/clang/include/clang/Driver/OffloadBundler.h b/clang/include/clang/Driver/OffloadBundler.h index 65d33bfbd2825f907c580b70684a36d41d1abd4e..57ecbdcb7d040e238eaf0b6d11009ec7ac0a605f 100644 --- a/clang/include/clang/Driver/OffloadBundler.h +++ b/clang/include/clang/Driver/OffloadBundler.h @@ -100,6 +100,7 @@ struct OffloadTargetInfo { // - Version (2 bytes) // - Compression Method (2 bytes) - Uses the values from // llvm::compression::Format. +// - Total file size (4 bytes). Available in version 2 and above. // - Uncompressed Size (4 bytes). // - Truncated MD5 Hash (8 bytes). // - Compressed Data (variable length). @@ -109,13 +110,17 @@ private: static inline const size_t MagicSize = 4; static inline const size_t VersionFieldSize = sizeof(uint16_t); static inline const size_t MethodFieldSize = sizeof(uint16_t); - static inline const size_t SizeFieldSize = sizeof(uint32_t); - static inline const size_t HashFieldSize = 8; - static inline const size_t HeaderSize = MagicSize + VersionFieldSize + - MethodFieldSize + SizeFieldSize + - HashFieldSize; + static inline const size_t FileSizeFieldSize = sizeof(uint32_t); + static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t); + static inline const size_t HashFieldSize = sizeof(uint64_t); + static inline const size_t V1HeaderSize = + MagicSize + VersionFieldSize + MethodFieldSize + + UncompressedSizeFieldSize + HashFieldSize; + static inline const size_t V2HeaderSize = + MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize + + UncompressedSizeFieldSize + HashFieldSize; static inline const llvm::StringRef MagicNumber = "CCOB"; - static inline const uint16_t Version = 1; + static inline const uint16_t Version = 2; public: static llvm::Expected> diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d83031b05cebc475448d7f792b3afacf456f028b..922bda721dc780bd141393ba28011353ceec46d3 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -807,8 +807,12 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">, "Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>, Visibility<[ClangOption, FlangOption]>, - HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " - "Clang will use the GCC installation with the largest version">; + HelpText< + "Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " + "Clang will use the GCC installation with the largest version">, + HelpTextForVariants<[FlangOption], + "Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " + "Flang will use the GCC installation with the largest version">; def gcc_triple_EQ : Joined<["--"], "gcc-triple=">, HelpText<"Search for the GCC installation with the specified triple.">; def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>, @@ -3100,6 +3104,11 @@ defm modules_skip_header_search_paths : BoolFOption<"modules-skip-header-search- HeaderSearchOpts<"ModulesSkipHeaderSearchPaths">, DefaultFalse, PosFlag, NegFlag, BothFlags<[], [CC1Option]>>; +def fno_modules_prune_non_affecting_module_map_files : + Flag<["-"], "fno-modules-prune-non-affecting-module-map-files">, + Group, Flags<[]>, Visibility<[CC1Option]>, + MarshallingInfoNegativeFlag>, + HelpText<"Do not prune non-affecting module map files when writing module files">; def fincremental_extensions : Flag<["-"], "fincremental-extensions">, @@ -4747,9 +4756,9 @@ def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group, HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group, HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; -def mstrict_align : Flag<["-"], "mstrict-align">, +def mstrict_align : Flag<["-"], "mstrict-align">, Group, HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">; -def mno_strict_align : Flag<["-"], "mno-strict-align">, +def mno_strict_align : Flag<["-"], "mno-strict-align">, Group, HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group, @@ -5032,6 +5041,12 @@ def maix_small_local_exec_tls : Flag<["-"], "maix-small-local-exec-tls">, "where the offset from the TLS base is encoded as an " "immediate operand (AIX 64-bit only). " "This access sequence is not used for variables larger than 32KB.">; +def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">, + Group, + HelpText<"Produce a faster access sequence for local-dynamic TLS variables " + "where the offset from the TLS base is encoded as an " + "immediate operand (AIX 64-bit only). " + "This access sequence is not used for variables larger than 32KB.">; def maix_struct_return : Flag<["-"], "maix-struct-return">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Return all structs in memory (PPC32 only)">, @@ -5493,6 +5508,14 @@ def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Visibility<[ClangOption, FlangOption]>, HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. " "When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">; +def frtlib_defaultlib : Flag<["-"], "frtlib-defaultlib">, + Visibility<[ClangOption, CLOption]>, + Group, + HelpText<"On Windows, emit /defaultlib: directives to link compiler-rt libraries (default)">; +def fno_rtlib_defaultlib : Flag<["-"], "fno-rtlib-defaultlib">, + Visibility<[ClangOption, CLOption]>, + Group, + HelpText<"On Windows, do not emit /defaultlib: directives to link compiler-rt libraries">; def offload_add_rpath: Flag<["--"], "offload-add-rpath">, Flags<[NoArgumentUnused]>, Alias; diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h index 637dc77e5d957ec70beecc0aa5edb53dfd978548..e4437ac0e35263db2a413a2f7cf11326976a6b21 100644 --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -252,6 +252,10 @@ public: LLVM_PREFERRED_TYPE(bool) unsigned ModulesSkipPragmaDiagnosticMappings : 1; + /// Whether to prune non-affecting module map files from PCM files. + LLVM_PREFERRED_TYPE(bool) + unsigned ModulesPruneNonAffectingModuleMaps : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ModulesHashContent : 1; @@ -280,7 +284,8 @@ public: ModulesValidateDiagnosticOptions(true), ModulesSkipDiagnosticOptions(false), ModulesSkipHeaderSearchPaths(false), - ModulesSkipPragmaDiagnosticMappings(false), ModulesHashContent(false), + ModulesSkipPragmaDiagnosticMappings(false), + ModulesPruneNonAffectingModuleMaps(true), ModulesHashContent(false), ModulesStrictContextHash(false), ModulesIncludeVFSUsage(false) {} /// AddPath - Add the \p Path path to the specified \p Group list. diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 643ddbdad8c87dbe038fbaa311f6497cac694cc8..2ed42d1c5f9aae9aef473d1d85c9cec885c5d1a5 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -80,7 +80,8 @@ public: bool isFloat128 : 1; // 1.0q bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk - bool isBitInt : 1; // 1wb, 1uwb (C23) + bool isBitInt : 1; // 1wb, 1uwb (C23) or 1__wb, 1__uwb (Clang extension in C++ + // mode) uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 72b2f958a5e622e90343b733dbd60aab0a26ed97..fb117bf04087ee4e528ae19b4dcebccdda57ce44 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -313,7 +313,15 @@ class Parser : public CodeCompletionHandler { /// top-level declaration is finished. SmallVector TemplateIds; + /// Don't destroy template annotations in MaybeDestroyTemplateIds even if + /// we're at the end of a declaration. Instead, we defer the destruction until + /// after a top-level declaration. + /// Use DelayTemplateIdDestructionRAII rather than setting it directly. + bool DelayTemplateIdDestruction = false; + void MaybeDestroyTemplateIds() { + if (DelayTemplateIdDestruction) + return; if (!TemplateIds.empty() && (Tok.is(tok::eof) || !PP.mightHavePendingAnnotationTokens())) DestroyTemplateIds(); @@ -329,6 +337,22 @@ class Parser : public CodeCompletionHandler { ~DestroyTemplateIdAnnotationsRAIIObj() { Self.MaybeDestroyTemplateIds(); } }; + struct DelayTemplateIdDestructionRAII { + Parser &Self; + bool PrevDelayTemplateIdDestruction; + + DelayTemplateIdDestructionRAII(Parser &Self, + bool DelayTemplateIdDestruction) noexcept + : Self(Self), + PrevDelayTemplateIdDestruction(Self.DelayTemplateIdDestruction) { + Self.DelayTemplateIdDestruction = DelayTemplateIdDestruction; + } + + ~DelayTemplateIdDestructionRAII() noexcept { + Self.DelayTemplateIdDestruction = PrevDelayTemplateIdDestruction; + } + }; + /// Identifiers which have been declared within a tentative parse. SmallVector TentativelyDeclaredIdentifiers; @@ -2967,25 +2991,25 @@ private: Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None, const IdentifierInfo *EnclosingScope = nullptr); - void MaybeParseHLSLSemantics(Declarator &D, - SourceLocation *EndLoc = nullptr) { - assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only"); + void MaybeParseHLSLAnnotations(Declarator &D, + SourceLocation *EndLoc = nullptr) { + assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only"); if (Tok.is(tok::colon)) { ParsedAttributes Attrs(AttrFactory); - ParseHLSLSemantics(Attrs, EndLoc); + ParseHLSLAnnotations(Attrs, EndLoc); D.takeAttributes(Attrs); } } - void MaybeParseHLSLSemantics(ParsedAttributes &Attrs, - SourceLocation *EndLoc = nullptr) { - assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only"); + void MaybeParseHLSLAnnotations(ParsedAttributes &Attrs, + SourceLocation *EndLoc = nullptr) { + assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only"); if (getLangOpts().HLSL && Tok.is(tok::colon)) - ParseHLSLSemantics(Attrs, EndLoc); + ParseHLSLAnnotations(Attrs, EndLoc); } - void ParseHLSLSemantics(ParsedAttributes &Attrs, - SourceLocation *EndLoc = nullptr); + void ParseHLSLAnnotations(ParsedAttributes &Attrs, + SourceLocation *EndLoc = nullptr); Decl *ParseHLSLBuffer(SourceLocation &DeclEnd); void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) { @@ -3644,10 +3668,22 @@ private: /// Parses the clause of the 'bind' argument, which can be a string literal or /// an ID expression. ExprResult ParseOpenACCBindClauseArgument(); + + /// A type to represent the state of parsing after an attempt to parse an + /// OpenACC int-expr. This is useful to determine whether an int-expr list can + /// continue parsing after a failed int-expr. + using OpenACCIntExprParseResult = + std::pair; /// Parses the clause kind of 'int-expr', which can be any integral /// expression. - ExprResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, - SourceLocation Loc); + OpenACCIntExprParseResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, + OpenACCClauseKind CK, + SourceLocation Loc); + /// Parses the argument list for 'num_gangs', which allows up to 3 + /// 'int-expr's. + bool ParseOpenACCIntExprList(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + SourceLocation Loc, + llvm::SmallVectorImpl &IntExprs); /// Parses the 'device-type-list', which is a list of identifiers. bool ParseOpenACCDeviceTypeList(); /// Parses the 'async-argument', which is an integral value with two diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 2bf91cb5212c5eb786c897e7ad7c916a59316290..993c9b1daa309b5fe8998cebd935a852b31ec737 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -65,7 +65,7 @@ public: /// Resolve a declaration ID into a declaration, potentially /// building a new declaration. - Decl *GetExternalDecl(uint32_t ID) override; + Decl *GetExternalDecl(Decl::DeclID ID) override; /// Complete the redeclaration chain if it's been extended since the /// previous generation of the AST source. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ffc58c681cdcd5a13a2d5816bb459a8246f8bf6a..1ca523ec88c2f9d5e2c3a6ddce57dc0fcb0d6a0a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3084,6 +3084,7 @@ public: Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D, SkipBodyInfo *SkipBody = nullptr, FnBodyKind BodyKind = FnBodyKind::Other); + void applyFunctionAttributesBeforeParsingBody(Decl *FD); /// Determine whether we can delay parsing the body of a function or /// function template until it is used, assuming we don't care about emitting @@ -6527,7 +6528,10 @@ public: SourceLocation RParenLoc); //// ActOnCXXThis - Parse 'this' pointer. - ExprResult ActOnCXXThis(SourceLocation loc); + ExprResult ActOnCXXThis(SourceLocation Loc); + + /// Check whether the type of 'this' is valid in the current context. + bool CheckCXXThisType(SourceLocation Loc, QualType Type); /// Build a CXXThisExpr and mark it referenced in the current context. Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); @@ -6949,10 +6953,14 @@ private: ///@{ public: + /// Check whether an expression might be an implicit class member access. + bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R, + bool IsAddressOfOperand); + ExprResult BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE = nullptr); + const TemplateArgumentListInfo *TemplateArgs, const Scope *S); + ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 023722049732afe03d3b655af4ab50f5c2a8119a..ea28617f79b81b65df7d5cc63050a55a07003adb 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -93,14 +93,16 @@ public: } unsigned getNumIntExprs() const { - assert((ClauseKind == OpenACCClauseKind::NumWorkers || + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); return std::get(Details).IntExprs.size(); } ArrayRef getIntExprs() { - assert((ClauseKind == OpenACCClauseKind::NumWorkers || + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); return std::get(Details).IntExprs; @@ -134,11 +136,19 @@ public: } void setIntExprDetails(ArrayRef IntExprs) { - assert((ClauseKind == OpenACCClauseKind::NumWorkers || + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}}; } + void setIntExprDetails(llvm::SmallVector &&IntExprs) { + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || + ClauseKind == OpenACCClauseKind::VectorLength) && + "Parsed clause kind does not have a int exprs"); + Details = IntExprDetails{IntExprs}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 500098dd3dab1d25e49cb350e67b2e5ce1ad104b..dcfa4ac0c1967797b8425ba53fd96fbe0e297edb 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -65,12 +65,85 @@ using IdentifierID = uint32_t; /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved. /// At the start of a chain of precompiled headers, declaration ID 1 is /// used for the translation unit declaration. +/// +/// FIXME: Merge with Decl::DeclID using DeclID = uint32_t; -// FIXME: Turn these into classes so we can have some type safety when -// we go from local ID to global and vice-versa. -using LocalDeclID = DeclID; -using GlobalDeclID = DeclID; +class LocalDeclID { +public: + explicit LocalDeclID(DeclID ID) : ID(ID) {} + + DeclID get() const { return ID; } + +private: + DeclID ID; +}; + +/// Wrapper class for DeclID. This is helpful to not mix the use of LocalDeclID +/// and GlobalDeclID to improve the type safety. +class GlobalDeclID { +public: + GlobalDeclID() : ID(0) {} + explicit GlobalDeclID(DeclID ID) : ID(ID) {} + + DeclID get() const { return ID; } + + explicit operator DeclID() const { return ID; } + + friend bool operator==(const GlobalDeclID &LHS, const GlobalDeclID &RHS) { + return LHS.ID == RHS.ID; + } + friend bool operator!=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) { + return LHS.ID != RHS.ID; + } + // We may sort the global decl ID. + friend bool operator<(const GlobalDeclID &LHS, const GlobalDeclID &RHS) { + return LHS.ID < RHS.ID; + } + friend bool operator>(const GlobalDeclID &LHS, const GlobalDeclID &RHS) { + return LHS.ID > RHS.ID; + } + friend bool operator<=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) { + return LHS.ID <= RHS.ID; + } + friend bool operator>=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) { + return LHS.ID >= RHS.ID; + } + +private: + DeclID ID; +}; + +/// A helper iterator adaptor to convert the iterators to `SmallVector` +/// to the iterators to `SmallVector`. +class GlobalDeclIDIterator + : public llvm::iterator_adaptor_base { +public: + GlobalDeclIDIterator() : iterator_adaptor_base(nullptr) {} + + GlobalDeclIDIterator(const DeclID *ID) : iterator_adaptor_base(ID) {} + + value_type operator*() const { return GlobalDeclID(*I); } + + bool operator==(const GlobalDeclIDIterator &RHS) const { return I == RHS.I; } +}; + +/// A helper iterator adaptor to convert the iterators to +/// `SmallVector` to the iterators to `SmallVector`. +class DeclIDIterator + : public llvm::iterator_adaptor_base { +public: + DeclIDIterator() : iterator_adaptor_base(nullptr) {} + + DeclIDIterator(const GlobalDeclID *ID) : iterator_adaptor_base(ID) {} + + value_type operator*() const { return DeclID(*I); } + + bool operator==(const DeclIDIterator &RHS) const { return I == RHS.I; } +}; /// An ID number that refers to a type in an AST file. /// @@ -2056,35 +2129,6 @@ enum CtorInitializerType { /// Kinds of cleanup objects owned by ExprWithCleanups. enum CleanupObjectKind { COK_Block, COK_CompoundLiteral }; -/// Describes the redeclarations of a declaration. -struct LocalRedeclarationsInfo { - // The ID of the first declaration - DeclID FirstID; - - // Offset into the array of redeclaration chains. - unsigned Offset; - - friend bool operator<(const LocalRedeclarationsInfo &X, - const LocalRedeclarationsInfo &Y) { - return X.FirstID < Y.FirstID; - } - - friend bool operator>(const LocalRedeclarationsInfo &X, - const LocalRedeclarationsInfo &Y) { - return X.FirstID > Y.FirstID; - } - - friend bool operator<=(const LocalRedeclarationsInfo &X, - const LocalRedeclarationsInfo &Y) { - return X.FirstID <= Y.FirstID; - } - - friend bool operator>=(const LocalRedeclarationsInfo &X, - const LocalRedeclarationsInfo &Y) { - return X.FirstID >= Y.FirstID; - } -}; - /// Describes the categories of an Objective-C class. struct ObjCCategoriesInfo { // The ID of the definition @@ -2187,6 +2231,27 @@ template <> struct DenseMapInfo { } }; +template <> struct DenseMapInfo { + using DeclID = clang::serialization::DeclID; + using GlobalDeclID = clang::serialization::GlobalDeclID; + + static GlobalDeclID getEmptyKey() { + return GlobalDeclID(DenseMapInfo::getEmptyKey()); + } + + static GlobalDeclID getTombstoneKey() { + return GlobalDeclID(DenseMapInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const GlobalDeclID &Key) { + return DenseMapInfo::getHashValue(Key.get()); + } + + static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) { + return L == R; + } +}; + } // namespace llvm #endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 1cd8b6a357cbf9575db6220956642d4450c81f60..ed917aa1642293154f6e61d42a9f44579cf15629 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -504,7 +504,7 @@ private: static_assert(std::is_same_v); using GlobalDeclMapType = - ContinuousRangeMap; + ContinuousRangeMap; /// Mapping from global declaration IDs to the module in which the /// declaration resides. @@ -513,14 +513,14 @@ private: using FileOffset = std::pair; using FileOffsetsTy = SmallVector; using DeclUpdateOffsetsMap = - llvm::DenseMap; + llvm::DenseMap; /// Declarations that have modifications residing in a later file /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; using DelayedNamespaceOffsetMapTy = llvm::DenseMap< - serialization::DeclID, + serialization::GlobalDeclID, std::pair>; /// Mapping from global declaration IDs to the lexical and visible block @@ -606,7 +606,11 @@ private: /// An array of lexical contents of a declaration context, as a sequence of /// Decl::Kind, DeclID pairs. - using LexicalContents = ArrayRef; + using unalighed_decl_id_t = + llvm::support::detail::packed_endian_specific_integral< + serialization::DeclID, llvm::endianness::native, + llvm::support::unaligned>; + using LexicalContents = ArrayRef; /// Map from a DeclContext to its lexical contents. llvm::DenseMap> @@ -631,7 +635,7 @@ private: /// Updates to the visible declarations of declaration contexts that /// haven't been loaded yet. - llvm::DenseMap + llvm::DenseMap PendingVisibleUpdates; /// The set of C++ or Objective-C classes that have forward @@ -658,7 +662,8 @@ private: /// Read the record that describes the visible contents of a DC. bool ReadVisibleDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, - uint64_t Offset, serialization::DeclID ID); + uint64_t Offset, + serialization::GlobalDeclID ID); /// A vector containing identifiers that have already been /// loaded. @@ -811,21 +816,26 @@ private: /// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks /// in the chain. The referenced declarations are deserialized and passed to /// the consumer eagerly. - SmallVector EagerlyDeserializedDecls; + SmallVector EagerlyDeserializedDecls; /// The IDs of all tentative definitions stored in the chain. /// /// Sema keeps track of all tentative definitions in a TU because it has to /// complete them and pass them on to CodeGen. Thus, tentative definitions in /// the PCH chain must be eagerly deserialized. - SmallVector TentativeDefinitions; + SmallVector TentativeDefinitions; /// The IDs of all CXXRecordDecls stored in the chain whose VTables are /// used. /// /// CodeGen has to emit VTables for these records, so they have to be eagerly /// deserialized. - SmallVector VTableUses; + struct VTableUse { + serialization::GlobalDeclID ID; + SourceLocation::UIntTy RawLoc; + bool Used; + }; + SmallVector VTableUses; /// A snapshot of the pending instantiations in the chain. /// @@ -833,7 +843,11 @@ private: /// end of the TU. It consists of a pair of values for every pending /// instantiation where the first value is the ID of the decl and the second /// is the instantiation location. - SmallVector PendingInstantiations; + struct PendingInstantiation { + serialization::GlobalDeclID ID; + SourceLocation::UIntTy RawLoc; + }; + SmallVector PendingInstantiations; //@} @@ -843,11 +857,11 @@ private: /// A snapshot of Sema's unused file-scoped variable tracking, for /// generating warnings. - SmallVector UnusedFileScopedDecls; + SmallVector UnusedFileScopedDecls; /// A list of all the delegating constructors we've seen, to diagnose /// cycles. - SmallVector DelegatingCtorDecls; + SmallVector DelegatingCtorDecls; /// Method selectors used in a @selector expression. Used for /// implementation of -Wselector. @@ -860,7 +874,7 @@ private: /// The IDs of type aliases for ext_vectors that exist in the chain. /// /// Used by Sema for finding sugared names for ext_vectors in diagnostics. - SmallVector ExtVectorDecls; + SmallVector ExtVectorDecls; //@} @@ -871,7 +885,7 @@ private: /// The IDs of all potentially unused typedef names in the chain. /// /// Sema tracks these to emit warnings. - SmallVector UnusedLocalTypedefNameCandidates; + SmallVector UnusedLocalTypedefNameCandidates; /// Our current depth in #pragma cuda force_host_device begin/end /// macros. @@ -880,7 +894,7 @@ private: /// The IDs of the declarations Sema stores directly. /// /// Sema tracks a few important decls, such as namespace std, directly. - SmallVector SemaDeclRefs; + SmallVector SemaDeclRefs; /// The IDs of the types ASTContext stores directly. /// @@ -891,7 +905,7 @@ private: /// /// The AST context tracks a few important decls, currently cudaConfigureCall, /// directly. - SmallVector CUDASpecialDeclRefs; + SmallVector CUDASpecialDeclRefs; /// The floating point pragma option settings. SmallVector FPPragmaOptions; @@ -940,11 +954,15 @@ private: llvm::DenseMap> OpenCLDeclExtMap; /// A list of the namespaces we've seen. - SmallVector KnownNamespaces; + SmallVector KnownNamespaces; /// A list of undefined decls with internal linkage followed by the /// SourceLocation of a matching ODR-use. - SmallVector UndefinedButUsed; + struct UndefinedButUsedDecl { + serialization::GlobalDeclID ID; + SourceLocation::UIntTy RawLoc; + }; + SmallVector UndefinedButUsed; /// Delete expressions to analyze at the end of translation unit. SmallVector DelayedDeleteExprs; @@ -956,7 +974,8 @@ private: /// The IDs of all decls to be checked for deferred diags. /// /// Sema tracks these to emit deferred diags. - llvm::SmallSetVector DeclsToCheckForDeferredDiags; + llvm::SmallSetVector + DeclsToCheckForDeferredDiags; private: struct ImportedSubmodule { @@ -1093,8 +1112,8 @@ private: /// /// The declarations on the identifier chain for these identifiers will be /// loaded once the recursive loading has completed. - llvm::MapVector> - PendingIdentifierInfos; + llvm::MapVector> + PendingIdentifierInfos; /// The set of lookup results that we have faked in order to support /// merging of partially deserialized decls but that we have not yet removed. @@ -1221,7 +1240,7 @@ private: SmallVector ObjCClassesLoaded; using KeyDeclsMap = - llvm::DenseMap>; + llvm::DenseMap>; /// A mapping from canonical declarations to the set of global /// declaration IDs for key declaration that have been merged with that @@ -1430,7 +1449,7 @@ private: QualType readTypeRecord(unsigned Index); RecordLocation TypeCursorForIndex(unsigned Index); void LoadedDecl(unsigned Index, Decl *D); - Decl *ReadDeclRecord(serialization::DeclID ID); + Decl *ReadDeclRecord(serialization::GlobalDeclID ID); void markIncompleteDeclChain(Decl *D); /// Returns the most recent declaration of a declaration (which must be @@ -1438,7 +1457,7 @@ private: /// merged into its redecl chain. Decl *getMostRecentExistingDecl(Decl *D); - RecordLocation DeclCursorForID(serialization::DeclID ID, + RecordLocation DeclCursorForID(serialization::GlobalDeclID ID, SourceLocation &Location); void loadDeclUpdateRecords(PendingUpdateRecord &Record); void loadPendingDeclChain(Decl *D, uint64_t LocalOffset); @@ -1897,8 +1916,8 @@ public: /// Map from a local declaration ID within a given module to a /// global declaration ID. - serialization::DeclID getGlobalDeclID(ModuleFile &F, - serialization::LocalDeclID LocalID) const; + serialization::GlobalDeclID + getGlobalDeclID(ModuleFile &F, serialization::LocalDeclID LocalID) const; /// Returns true if global DeclID \p ID originated from module \p M. bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const; @@ -1912,23 +1931,23 @@ public: /// Resolve a declaration ID into a declaration, potentially /// building a new declaration. - Decl *GetDecl(serialization::DeclID ID); - Decl *GetExternalDecl(uint32_t ID) override; + Decl *GetDecl(serialization::GlobalDeclID ID); + Decl *GetExternalDecl(Decl::DeclID ID) override; /// Resolve a declaration ID into a declaration. Return 0 if it's not /// been loaded yet. - Decl *GetExistingDecl(serialization::DeclID ID); + Decl *GetExistingDecl(serialization::GlobalDeclID ID); /// Reads a declaration with the given local ID in the given module. - Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) { + Decl *GetLocalDecl(ModuleFile &F, serialization::LocalDeclID LocalID) { return GetDecl(getGlobalDeclID(F, LocalID)); } /// Reads a declaration with the given local ID in the given module. /// /// \returns The requested declaration, casted to the given return type. - template - T *GetLocalDeclAs(ModuleFile &F, uint32_t LocalID) { + template + T *GetLocalDeclAs(ModuleFile &F, serialization::LocalDeclID LocalID) { return cast_or_null(GetLocalDecl(F, LocalID)); } @@ -1939,14 +1958,14 @@ public: /// module file. serialization::DeclID mapGlobalIDToModuleFileGlobalID(ModuleFile &M, - serialization::DeclID GlobalID); + serialization::GlobalDeclID GlobalID); /// Reads a declaration ID from the given position in a record in the /// given module. /// /// \returns The declaration ID read from the record, adjusted to a global ID. - serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record, - unsigned &Idx); + serialization::GlobalDeclID + ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx); /// Reads a declaration from the given position in a record in the /// given module. @@ -2120,9 +2139,10 @@ public: void LoadSelector(Selector Sel); void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); - void SetGloballyVisibleDecls(IdentifierInfo *II, - const SmallVectorImpl &DeclIDs, - SmallVectorImpl *Decls = nullptr); + void SetGloballyVisibleDecls( + IdentifierInfo *II, + const SmallVectorImpl &DeclIDs, + SmallVectorImpl *Decls = nullptr); /// Report a diagnostic. DiagnosticBuilder Diag(unsigned DiagID) const; @@ -2363,7 +2383,7 @@ public: // Contains the IDs for declarations that were requested before we have // access to a Sema object. - SmallVector PreloadedDeclIDs; + SmallVector PreloadedDeclIDs; /// Retrieve the semantic analysis object used to analyze the /// translation unit in which the precompiled header is being diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index 7dd1140106e47c6199e60a7e0186864e571b0627..9eaf50a76d52f4c6f5ec33a65c4385855cda80c4 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -103,13 +103,6 @@ public: DC); } - /// Read the record that describes the visible contents of a DC. - bool readVisibleDeclContextStorage(uint64_t Offset, - serialization::DeclID ID) { - return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset, - ID); - } - ExplicitSpecifier readExplicitSpec() { uint64_t Kind = readInt(); bool HasExpr = Kind & 0x1; @@ -143,8 +136,7 @@ public: /// Reads a declaration with the given local ID in the given module. /// /// \returns The requested declaration, casted to the given return type. - template - T *GetLocalDeclAs(uint32_t LocalID) { + template T *GetLocalDeclAs(serialization::LocalDeclID LocalID) { return cast_or_null(Reader->GetLocalDecl(*F, LocalID)); } @@ -190,7 +182,7 @@ public: /// Reads a declaration ID from the given position in this record. /// /// \returns The declaration ID read from the record, adjusted to a global ID. - serialization::DeclID readDeclID() { + serialization::GlobalDeclID readDeclID() { return Reader->ReadDeclID(*F, Record, Idx); } diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index bc0aa89966c2b4f78a24cebded1d311e2efc3eb5..492c35dceb08d4f08b3ddbeab49b7976b4e1ecdb 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -462,7 +462,7 @@ public: serialization::DeclID BaseDeclID = 0; /// Remapping table for declaration IDs in this module. - ContinuousRangeMap DeclRemap; + ContinuousRangeMap DeclRemap; /// Mapping from the module files that this module file depends on /// to the base declaration ID for that module as it is understood within this @@ -474,7 +474,7 @@ public: llvm::DenseMap GlobalToLocalDeclIDs; /// Array of file-level DeclIDs sorted by file. - const serialization::DeclID *FileSortedDecls = nullptr; + const serialization::LocalDeclID *FileSortedDecls = nullptr; unsigned NumFileSortedDecls = 0; /// Array of category list location information within this diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b974fc28283c775ee1a24ae7c9cb67f3bc99c0e6..0f894c623beeeaf44dc2a1e52ccd9dc48315830d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1083,7 +1083,8 @@ void ASTContext::addModuleInitializer(Module *M, Decl *D) { Inits->Initializers.push_back(D); } -void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef IDs) { +void ASTContext::addLazyModuleInitializers(Module *M, + ArrayRef IDs) { auto *&Inits = ModuleInitializers[M]; if (!Inits) Inits = new (*this) PerModuleInitializers; @@ -7241,6 +7242,14 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { // We perform that promotion here to match GCC and C++. // FIXME: C does not permit promotion of an enum bit-field whose rank is // greater than that of 'int'. We perform that promotion to match GCC. + // + // C23 6.3.1.1p2: + // The value from a bit-field of a bit-precise integer type is converted to + // the corresponding bit-precise integer type. (The rest is the same as in + // C11.) + if (QualType QT = Field->getType(); QT->isBitIntType()) + return QT; + if (BitWidth < IntSize) return IntTy; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 6aaa34c55ce3078510f4210edcc4fa11259c2739..60f213322b346bb8b06a7a569989731aeb8f7de0 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -695,7 +695,7 @@ namespace clang { // Returns true if the given function has a placeholder return type and // that type is declared inside the body of the function. // E.g. auto f() { struct X{}; return X(); } - bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D); + bool hasReturnTypeDeclaredInside(FunctionDecl *D); }; template @@ -3647,15 +3647,28 @@ private: }; } // namespace -/// This function checks if the function has 'auto' return type that contains +/// This function checks if the given function has a return type that contains /// a reference (in any way) to a declaration inside the same function. -bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { +bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs(); assert(FromFPT && "Must be called on FunctionProtoType"); + auto IsCXX11LambdaWithouTrailingReturn = [&]() { + if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later + return false; + + if (FromFPT->hasTrailingReturn()) + return false; + + if (const auto *MD = dyn_cast(D)) + return cast(MD->getDeclContext())->isLambda(); + + return false; + }; + QualType RetT = FromFPT->getReturnType(); - if (isa(RetT.getTypePtr())) { + if (isa(RetT.getTypePtr()) || IsCXX11LambdaWithouTrailingReturn()) { FunctionDecl *Def = D->getDefinition(); IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D); return Visitor.CheckType(RetT); @@ -3811,7 +3824,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // E.g.: auto foo() { struct X{}; return X(); } // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified return type. - if (hasAutoReturnTypeDeclaredInside(D)) { + if (hasReturnTypeDeclaredInside(D)) { FromReturnTy = Importer.getFromContext().VoidTy; UsedDifferentProtoType = true; } @@ -8561,8 +8574,8 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, - ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(), - ToDecls.end()); + ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), + /*KnownDependent=*/E->isTypeDependent()); } ExpectedStmt diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 0ba271c3e04ee5ddf91cb5138c8e77dfadd4ff54..67bb9e41e3e61e75d05baeeac4e102a9572a1de4 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -337,7 +337,7 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const { CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr(); if (CommonBasePtr->LazySpecializations) { ASTContext &Context = getASTContext(); - uint32_t *Specs = CommonBasePtr->LazySpecializations; + Decl::DeclID *Specs = CommonBasePtr->LazySpecializations; CommonBasePtr->LazySpecializations = nullptr; for (uint32_t I = 0, N = *Specs++; I != N; ++I) (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index a581963188433e014cb4a3d74f974cbc2274028c..7e9343271ac3cfd551026ab3c0d54d7bced980e4 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -353,7 +353,7 @@ SourceLocation CXXPseudoDestructorExpr::getEndLoc() const { UnresolvedLookupExpr::UnresolvedLookupExpr( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, + const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, @@ -361,7 +361,6 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( KnownDependent, false, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; - UnresolvedLookupExprBits.Overloaded = Overloaded; } UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty, @@ -373,15 +372,16 @@ UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty, UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { + bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent) { unsigned NumResults = End - Begin; unsigned Size = totalSizeToAlloc(NumResults, 0, 0); void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, - SourceLocation(), NameInfo, RequiresADL, - Overloaded, nullptr, Begin, End, false); + return new (Mem) UnresolvedLookupExpr( + Context, NamingClass, QualifierLoc, + /*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL, + /*TemplateArgs=*/nullptr, Begin, End, KnownDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::Create( @@ -390,16 +390,16 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent) { - assert(Args || TemplateKWLoc.isValid()); unsigned NumResults = End - Begin; + bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid(); unsigned NumTemplateArgs = Args ? Args->size() : 0; - unsigned Size = - totalSizeToAlloc(NumResults, 1, NumTemplateArgs); + unsigned Size = totalSizeToAlloc( + NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr( - Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL, - /*Overloaded=*/true, Args, Begin, End, KnownDependent); + return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, + TemplateKWLoc, NameInfo, RequiresADL, + Args, Begin, End, KnownDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty( diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 73ae8d8efb23a28d372ef170bcb05ce7f4089882..de3c2a63913e94295d0a3007231b70e04c2318aa 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -16853,13 +16853,13 @@ bool Expr::EvaluateCharRangeAsString(std::string &Result, if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) return false; - int64_t Size = SizeValue.getExtValue(); + uint64_t Size = SizeValue.getZExtValue(); if (!::EvaluatePointer(PtrExpression, String, Info)) return false; QualType CharTy = PtrExpression->getType()->getPointeeType(); - for (int64_t I = 0; I < Size; ++I) { + for (uint64_t I = 0; I < Size; ++I) { APValue Char; if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, Char)) diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index 090ef02aa4224d65c5942579a1556a3957369bd4..2e54d9f9af1c6d571c4f83566cb63f0ae7036d7c 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -68,9 +68,7 @@ bool ExternalASTSource::layoutRecordType( return false; } -Decl *ExternalASTSource::GetExternalDecl(uint32_t ID) { - return nullptr; -} +Decl *ExternalASTSource::GetExternalDecl(Decl::DeclID ID) { return nullptr; } Selector ExternalASTSource::GetExternalSelector(uint32_t ID) { return Selector(); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index f317f506d24f4b9fe8f962d27fbe3f010899c4d4..8cd0c198d9a844d6de48d284b4a4321bffbfd22a 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -194,6 +194,12 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return false; PrimType T = classifyPrim(CE->getType()); + if (T == PT_IntAP) + return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()), + CE); + if (T == PT_IntAPS) + return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()), + CE); return this->emitCastPointerIntegral(T, CE); } @@ -922,9 +928,9 @@ bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueIni return true; } - if (QT->isAnyComplexType()) { + if (const auto *ComplexTy = E->getType()->getAs()) { assert(Initializing); - QualType ElemQT = QT->getAs()->getElementType(); + QualType ElemQT = ComplexTy->getElementType(); PrimType ElemT = classifyPrim(ElemQT); for (unsigned I = 0; I < 2; ++I) { if (!this->visitZeroInitializer(ElemT, ElemQT, E)) @@ -935,6 +941,20 @@ bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueIni return true; } + if (const auto *VecT = E->getType()->getAs()) { + unsigned NumVecElements = VecT->getNumElements(); + QualType ElemQT = VecT->getElementType(); + PrimType ElemT = classifyPrim(ElemQT); + + for (unsigned I = 0; I < NumVecElements; ++I) { + if (!this->visitZeroInitializer(ElemT, ElemQT, E)) + return false; + if (!this->emitInitElem(ElemT, I, E)) + return false; + } + return true; + } + return false; } @@ -1098,13 +1118,13 @@ bool ByteCodeExprGen::VisitInitListExpr(const InitListExpr *E) { return true; } - if (T->isAnyComplexType()) { + if (const auto *ComplexTy = E->getType()->getAs()) { unsigned NumInits = E->getNumInits(); if (NumInits == 1) return this->delegate(E->inits()[0]); - QualType ElemQT = E->getType()->getAs()->getElementType(); + QualType ElemQT = ComplexTy->getElementType(); PrimType ElemT = classifyPrim(ElemQT); if (NumInits == 0) { // Zero-initialize both elements. @@ -1337,6 +1357,8 @@ bool ByteCodeExprGen::VisitMemberExpr(const MemberExpr *E) { if (const auto *FD = dyn_cast(Member)) { const RecordDecl *RD = FD->getParent(); const Record *R = getRecord(RD); + if (!R) + return false; const Record::Field *F = R->getField(FD); // Leave a pointer to the field on the stack. if (F->Decl->getType()->isReferenceType()) diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index 55a06f37a0c3dec8296174593d35c07579e53f80..36dab6252ece67a4071ed3b338e28f9524a3db3e 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -675,7 +675,30 @@ bool ByteCodeStmtGen::visitDefaultStmt(const DefaultStmt *S) { template bool ByteCodeStmtGen::visitAttributedStmt(const AttributedStmt *S) { - // Ignore all attributes. + + for (const Attr *A : S->getAttrs()) { + auto *AA = dyn_cast(A); + if (!AA) + continue; + + assert(isa(S->getSubStmt())); + + const Expr *Assumption = AA->getAssumption(); + if (Assumption->isValueDependent()) + return false; + + if (Assumption->HasSideEffects(this->Ctx.getASTContext())) + continue; + + // Evaluate assumption. + if (!this->visitBool(Assumption)) + return false; + + if (!this->emitAssume(Assumption)) + return false; + } + + // Ignore other attributes. return this->visitStmt(S->getSubStmt()); } diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index bab9774288bfa6e127f5ddead8e0fa334dd4c3b5..fb7ee14515715aa6696c7de240715d6542e8c088 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -154,7 +154,10 @@ public: } IntegralAP truncate(unsigned BitWidth) const { - return IntegralAP(V.trunc(BitWidth)); + if constexpr (Signed) + return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth())); + else + return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth())); } IntegralAP toUnsigned() const { diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index dd0bacd73acb107f1280eb929cf75d886a617754..9283f697c007098804c8486cc9f0c4d31635f846 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1548,17 +1548,16 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, if (!CheckArray(S, OpPC, Ptr)) return false; - // Get a version of the index comparable to the type. - T Index = T::from(Ptr.getIndex(), Offset.bitWidth()); - // Compute the largest index into the array. - T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth()); + uint64_t Index = Ptr.getIndex(); + uint64_t MaxIndex = static_cast(Ptr.getNumElems()); bool Invalid = false; // Helper to report an invalid offset, computed as APSInt. auto DiagInvalidOffset = [&]() -> void { const unsigned Bits = Offset.bitWidth(); - APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false); - APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false); + APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), /*IsUnsigend=*/false); + APSInt APIndex(APInt(Bits + 2, Index, /*IsSigned=*/true), + /*IsUnsigned=*/false); APSInt NewIndex = (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index) @@ -1569,22 +1568,24 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, }; if (Ptr.isBlockPointer()) { - T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth()); + uint64_t IOffset = static_cast(Offset); + uint64_t MaxOffset = MaxIndex - Index; + if constexpr (Op == ArithOp::Add) { // If the new offset would be negative, bail out. - if (Offset.isNegative() && (Offset.isMin() || -Offset > Index)) + if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index)) DiagInvalidOffset(); // If the new offset would be out of bounds, bail out. - if (Offset.isPositive() && Offset > MaxOffset) + if (Offset.isPositive() && IOffset > MaxOffset) DiagInvalidOffset(); } else { // If the new offset would be negative, bail out. - if (Offset.isPositive() && Index < Offset) + if (Offset.isPositive() && Index < IOffset) DiagInvalidOffset(); // If the new offset would be out of bounds, bail out. - if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset)) + if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset)) DiagInvalidOffset(); } } @@ -1601,7 +1602,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, else Result = WideIndex - WideOffset; - S.Stk.push(Ptr.atIndex(static_cast(Result))); + S.Stk.push(Ptr.atIndex(static_cast(Result))); return true; } @@ -1832,6 +1833,32 @@ bool CastPointerIntegral(InterpState &S, CodePtr OpPC) { return true; } +static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, + uint32_t BitWidth) { + const Pointer &Ptr = S.Stk.pop(); + + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + + S.Stk.push>( + IntegralAP::from(Ptr.getIntegerRepresentation(), BitWidth)); + return true; +} + +static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, + uint32_t BitWidth) { + const Pointer &Ptr = S.Stk.pop(); + + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + + S.Stk.push>( + IntegralAP::from(Ptr.getIntegerRepresentation(), BitWidth)); + return true; +} + //===----------------------------------------------------------------------===// // Zero, Nullptr //===----------------------------------------------------------------------===// @@ -2300,6 +2327,18 @@ inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, return CheckDeclRef(S, OpPC, DR); } +inline bool Assume(InterpState &S, CodePtr OpPC) { + const auto Val = S.Stk.pop(); + + if (Val) + return true; + + // Else, diagnose. + const SourceLocation &Loc = S.Current->getLocation(OpPC); + S.CCEDiag(Loc, diag::note_constexpr_assumption_failed); + return false; +} + template ::T> inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) { llvm::SmallVector ArrayIndices; diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index f562f9e1cb19fb7770537d8cfe40df49dfe927d3..565c85bc2e0c218c8135b3cf68c0cc0af04eda7d 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -9,6 +9,7 @@ #include "Boolean.h" #include "Interp.h" #include "PrimType.h" +#include "clang/AST/OSLog.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" @@ -1088,6 +1089,17 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, return false; } +static bool interp__builtin_os_log_format_buffer_size(InterpState &S, + CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + analyze_os_log::OSLogBufferLayout Layout; + analyze_os_log::computeOSLogBufferLayout(S.getCtx(), Call, Layout); + pushInteger(S, Layout.size().getQuantity(), Call->getType()); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { const InterpFrame *Frame = S.Current; @@ -1409,6 +1421,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_os_log_format_buffer_size: + if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call)) + return false; + break; + default: S.FFDiag(S.Current->getLocation(OpPC), diag::note_invalid_subexpr_in_const_expr) diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index e17be3afd25729a7f3a1b78fcb425af3d16ae1fa..742785b28eb4d7131cd862b0dbad87a5495e75be 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -664,10 +664,19 @@ def CastFloatingIntegralAPS : Opcode { } def CastPointerIntegral : Opcode { - let Types = [AluTypeClass]; - let Args = []; + let Types = [FixedSizeIntegralTypeClass]; let HasGroup = 1; } +def CastPointerIntegralAP : Opcode { + let Types = []; + let HasGroup = 0; + let Args = [ArgUint32]; +} +def CastPointerIntegralAPS : Opcode { + let Types = []; + let HasGroup = 0; + let Args = [ArgUint32]; +} def DecayPtr : Opcode { let Types = [PtrTypeClass, PtrTypeClass]; @@ -727,6 +736,8 @@ def InvalidDeclRef : Opcode { let Args = [ArgDeclRef]; } +def Assume : Opcode; + def ArrayDecay : Opcode; def CheckNonNullArg : Opcode { diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index e163e658d462b2d2020900e95d27798461c41f4c..5ef31671ae7be51c8d3caae38b9f633600576ede 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -23,7 +23,7 @@ Pointer::Pointer(Block *Pointee) : Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(), Pointee->getDescriptor()->getMetadataSize()) {} -Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset) +Pointer::Pointer(Block *Pointee, uint64_t BaseAndOffset) : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {} Pointer::Pointer(const Pointer &P) @@ -34,7 +34,7 @@ Pointer::Pointer(const Pointer &P) PointeeStorage.BS.Pointee->addPointer(this); } -Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset) +Pointer::Pointer(Block *Pointee, unsigned Base, uint64_t Offset) : Offset(Offset), StorageKind(Storage::Block) { assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base"); diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index b4475577b74625bdb147ee22eb134aab2d7ac2e5..c4d701bc71b7bf58fde85730a47e74e26eecc5dc 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -89,10 +89,10 @@ public: PointeeStorage.Int.Desc = nullptr; } Pointer(Block *B); - Pointer(Block *B, unsigned BaseAndOffset); + Pointer(Block *B, uint64_t BaseAndOffset); Pointer(const Pointer &P); Pointer(Pointer &&P); - Pointer(uint64_t Address, const Descriptor *Desc, unsigned Offset = 0) + Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0) : Offset(Offset), StorageKind(Storage::Int) { PointeeStorage.Int.Value = Address; PointeeStorage.Int.Desc = Desc; @@ -134,14 +134,14 @@ public: std::optional toRValue(const Context &Ctx) const; /// Offsets a pointer inside an array. - [[nodiscard]] Pointer atIndex(unsigned Idx) const { + [[nodiscard]] Pointer atIndex(uint64_t Idx) const { if (isIntegralPointer()) return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx); if (asBlockPointer().Base == RootPtrMark) return Pointer(asBlockPointer().Pointee, RootPtrMark, getDeclDesc()->getSize()); - unsigned Off = Idx * elemSize(); + uint64_t Off = Idx * elemSize(); if (getFieldDesc()->ElemDesc) Off += sizeof(InlineDescriptor); else @@ -630,7 +630,7 @@ private: friend class DeadBlock; friend struct InitMap; - Pointer(Block *Pointee, unsigned Base, unsigned Offset); + Pointer(Block *Pointee, unsigned Base, uint64_t Offset); /// Returns the embedded descriptor preceding a field. InlineDescriptor *getInlineDesc() const { @@ -656,7 +656,7 @@ private: } /// Offset into the storage. - unsigned Offset = 0; + uint64_t Offset = 0; /// Previous link in the pointer chain. Pointer *Prev = nullptr; diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 2c8c6781b3483344f6f271c5b84c00993f44d1ff..3773e0662f784ce3b9f23224ee5150f5c1caaf73 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -108,27 +108,23 @@ Pointer Program::getPtrGlobal(unsigned Idx) const { } std::optional Program::getGlobal(const ValueDecl *VD) { - auto It = GlobalIndices.find(VD); - if (It != GlobalIndices.end()) + if (auto It = GlobalIndices.find(VD); It != GlobalIndices.end()) return It->second; // Find any previous declarations which were already evaluated. std::optional Index; - for (const Decl *P = VD; P; P = P->getPreviousDecl()) { - auto It = GlobalIndices.find(P); - if (It != GlobalIndices.end()) { + for (const Decl *P = VD->getPreviousDecl(); P; P = P->getPreviousDecl()) { + if (auto It = GlobalIndices.find(P); It != GlobalIndices.end()) { Index = It->second; break; } } // Map the decl to the existing index. - if (Index) { + if (Index) GlobalIndices[VD] = *Index; - return std::nullopt; - } - return Index; + return std::nullopt; } std::optional Program::getOrCreateGlobal(const ValueDecl *VD, @@ -173,7 +169,6 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { std::optional Program::createGlobal(const ValueDecl *VD, const Expr *Init) { - assert(!getGlobal(VD)); bool IsStatic, IsExtern; if (const auto *Var = dyn_cast(VD)) { IsStatic = Context::shouldBeGloballyIndexed(VD); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c3b98d2d2149cb589da0286d95f323b0b9e8783b..106c69dd5beed718256fc003af4caee51f475909 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1062,26 +1062,23 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // ::= // const DeclContext *DC = Context.getEffectiveDeclContext(ND); + bool IsLambda = isLambda(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. // FIXME: This is a hack; extern variables declared locally should have // a proper semantic declaration context! - if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) + if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = Context.getEffectiveParentContext(DC); - else if (GetLocalClassDecl(ND)) { + else if (GetLocalClassDecl(ND) && + (!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) { mangleLocalName(GD, AdditionalAbiTags); return; } assert(!isa(DC) && "context cannot be LinkageSpecDecl"); - if (isLocalContainerContext(DC)) { - mangleLocalName(GD, AdditionalAbiTags); - return; - } - // Closures can require a nested-name mangling even if they're semantically // in the global namespace. if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { @@ -1089,6 +1086,11 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, return; } + if (isLocalContainerContext(DC)) { + mangleLocalName(GD, AdditionalAbiTags); + return; + } + if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; @@ -2201,8 +2203,6 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (NoFunction && isLocalContainerContext(DC)) return; - assert(!isLocalContainerContext(DC)); - const NamedDecl *ND = cast(DC); if (mangleSubstitution(ND)) return; diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index 75334223e073c32feb9c65d657a429826c8e8438..6cd5b28802187de369e264ecb50f610fc16d98bc 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -124,6 +124,16 @@ OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc, OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc); } +OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + ArrayRef IntExprs, + SourceLocation EndLoc) { + void *Mem = C.Allocate( + OpenACCNumGangsClause::totalSizeToAlloc(IntExprs.size())); + return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -141,6 +151,12 @@ void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) { OS << "(" << CondExpr << ")"; } +void OpenACCClausePrinter::VisitNumGangsClause(const OpenACCNumGangsClause &C) { + OS << "num_gangs("; + llvm::interleaveComma(C.getIntExprs(), OS); + OS << ")"; +} + void OpenACCClausePrinter::VisitNumWorkersClause( const OpenACCNumWorkersClause &C) { OS << "num_workers(" << C.getIntExpr() << ")"; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8138ae3a244a8baba6be68dac233308cd36fc46d..c81724f84dd9cee09aed44aa37b6819cd2d2b613 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2497,6 +2497,12 @@ void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) { Profiler.VisitStmt(Clause.getConditionExpr()); } +void OpenACCClauseProfiler::VisitNumGangsClause( + const OpenACCNumGangsClause &Clause) { + for (auto *E : Clause.getIntExprs()) + Profiler.VisitStmt(E); +} + void OpenACCClauseProfiler::VisitNumWorkersClause( const OpenACCNumWorkersClause &Clause) { assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr"); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e5a8b285715b3096c45dd9cbf5211d7125108fce..8f0a9a9b0ed0bcd0659571935f450e59737b401e 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -399,6 +399,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { break; case OpenACCClauseKind::If: case OpenACCClauseKind::Self: + case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::VectorLength: // The condition expression will be printed as a part of the 'children', diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index c76ddf17b719d4c1ee62177fba6d4a6eb3f0727d..0e640cbada726868b218e53333f46430c3d9ce1d 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -937,7 +937,7 @@ class MapAnyOfMatcherDescriptor : public MatcherDescriptor { public: MapAnyOfMatcherDescriptor(ASTNodeKind CladeNodeKind, std::vector NodeKinds) - : CladeNodeKind(CladeNodeKind), NodeKinds(NodeKinds) {} + : CladeNodeKind(CladeNodeKind), NodeKinds(std::move(NodeKinds)) {} VariantMatcher create(SourceRange NameRange, ArrayRef Args, Diagnostics *Error) const override { @@ -1026,7 +1026,7 @@ public: } return std::make_unique(CladeNodeKind, - NodeKinds); + std::move(NodeKinds)); } bool isVariadic() const override { return true; } diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp index 6f179c1403b6f58700366d1c6e242ebfaf855c7f..619bf772bba5eec46215759e62e197176e2d7718 100644 --- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp @@ -261,4 +261,10 @@ ReferencedDecls getReferencedDecls(const FunctionDecl &FD) { return Result; } +ReferencedDecls getReferencedDecls(const Stmt &S) { + ReferencedDecls Result; + getReferencedDecls(S, Result); + return Result; +} + } // namespace clang::dataflow diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 05395e07a7a68cc035a7ca281d21cfe1b05e0e9e..3cb656adcbdc0cfa5ba8fa15cc0223d1e03f1011 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -237,13 +237,8 @@ joinLocToVal(const llvm::MapVector &LocToVal, continue; assert(It->second != nullptr); - if (areEquivalentValues(*Val, *It->second)) { - Result.insert({Loc, Val}); - continue; - } - - if (Value *JoinedVal = joinDistinctValues( - Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) { + if (Value *JoinedVal = Environment::joinValues( + Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) { Result.insert({Loc, JoinedVal}); } } @@ -775,27 +770,16 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal; JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; - if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) { - // `ReturnVal` might not always get set -- for example if we have a return - // statement of the form `return some_other_func()` and we decide not to - // analyze `some_other_func()`. - // In this case, we can't say anything about the joined return value -- we - // don't simply want to propagate the return value that we do have, because - // it might not be the correct one. - // This occurs for example in the test `ContextSensitiveMutualRecursion`. + if (EnvA.CallStack.empty()) { JoinedEnv.ReturnVal = nullptr; - } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) { - JoinedEnv.ReturnVal = EnvA.ReturnVal; } else { - assert(!EnvA.CallStack.empty()); // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this // cast. auto *Func = dyn_cast(EnvA.CallStack.back()); assert(Func != nullptr); - if (Value *JoinedVal = - joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA, - *EnvB.ReturnVal, EnvB, JoinedEnv, Model)) - JoinedEnv.ReturnVal = JoinedVal; + JoinedEnv.ReturnVal = + joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal, + EnvB, JoinedEnv, Model); } if (EnvA.ReturnLoc == EnvB.ReturnLoc) @@ -821,6 +805,24 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, return JoinedEnv; } +Value *Environment::joinValues(QualType Ty, Value *Val1, + const Environment &Env1, Value *Val2, + const Environment &Env2, Environment &JoinedEnv, + Environment::ValueModel &Model) { + if (Val1 == nullptr || Val2 == nullptr) + // We can't say anything about the joined value -- even if one of the values + // is non-null, we don't want to simply propagate it, because it would be + // too specific: Because the other value is null, that means we have no + // information at all about the value (i.e. the value is unconstrained). + return nullptr; + + if (areEquivalentValues(*Val1, *Val2)) + // Arbitrarily return one of the two values. + return Val1; + + return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model); +} + StorageLocation &Environment::createStorageLocation(QualType Type) { return DACtx->createStorageLocation(Type); } diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 2771c8b2e37ebb7e114f60de6b2ea47370504828..43fdfa5abcbb51fd3aaeb130156fc8fadc4be38b 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -124,8 +124,9 @@ namespace { class TransferVisitor : public ConstStmtVisitor { public: - TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env) - : StmtToEnv(StmtToEnv), Env(Env) {} + TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, + Environment::ValueModel &Model) + : StmtToEnv(StmtToEnv), Env(Env), Model(Model) {} void VisitBinaryOperator(const BinaryOperator *S) { const Expr *LHS = S->getLHS(); @@ -641,17 +642,42 @@ public: } void VisitConditionalOperator(const ConditionalOperator *S) { - // FIXME: Revisit this once flow conditions are added to the framework. For - // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow - // condition. - // When we do this, we will need to retrieve the values of the operands from - // the environments for the basic blocks they are computed in, in a similar - // way to how this is done for short-circuited logical operators in - // `getLogicOperatorSubExprValue()`. - if (S->isGLValue()) - Env.setStorageLocation(*S, Env.createObject(S->getType())); - else if (!S->getType()->isRecordType()) { - if (Value *Val = Env.createValue(S->getType())) + const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr()); + const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr()); + + if (TrueEnv == nullptr || FalseEnv == nullptr) { + // If the true or false branch is dead, we may not have an environment for + // it. We could handle this specifically by forwarding the value or + // location of the live branch, but this case is rare enough that this + // probably isn't worth the additional complexity. + return; + } + + if (S->isGLValue()) { + StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr()); + StorageLocation *FalseLoc = + FalseEnv->getStorageLocation(*S->getFalseExpr()); + if (TrueLoc == FalseLoc && TrueLoc != nullptr) + Env.setStorageLocation(*S, *TrueLoc); + } else if (!S->getType()->isRecordType()) { + // The conditional operator can evaluate to either of the values of the + // two branches. To model this, join these two values together to yield + // the result of the conditional operator. + // Note: Most joins happen in `computeBlockInputState()`, but this case is + // different: + // - `computeBlockInputState()` (which in turn calls `Environment::join()` + // joins values associated with the _same_ expression or storage + // location, then associates the joined value with that expression or + // storage location. This join has nothing to do with transfer -- + // instead, it joins together the results of performing transfer on two + // different blocks. + // - Here, we join values associated with _different_ expressions (the + // true and false branch), then associate the joined value with a third + // expression (the conditional operator itself). This join is what it + // means to perform transfer on the conditional operator. + if (Value *Val = Environment::joinValues( + S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv, + FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model)) Env.setValue(*S, *Val); } } @@ -810,12 +836,14 @@ private: const StmtToEnvMap &StmtToEnv; Environment &Env; + Environment::ValueModel &Model; }; } // namespace -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) { - TransferVisitor(StmtToEnv, Env).Visit(&S); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, + Environment::ValueModel &Model) { + TransferVisitor(StmtToEnv, Env, Model).Visit(&S); } } // namespace dataflow diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 71d5c1a6c4f4a36fc818474c57bb568108b354d4..12eff4dd4b781d8acf3f64b477b5ee52a1d25d07 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -316,7 +316,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt, const Stmt *S = Elt.getStmt(); assert(S != nullptr); transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S, - InputState.Env); + InputState.Env, AC.Analysis); } /// Built-in transfer function for `CFGInitializer`. @@ -452,7 +452,7 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC, // terminator condition, but not as a `CFGElement`. The condition of an if // statement is one such example. transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State), - *TerminatorCond, State.Env); + *TerminatorCond, State.Env, AC.Analysis); // If the transfer function didn't produce a value, create an atom so that // we have *some* value for the condition expression. This ensures that diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index aebe51bfa4daadb72abee05249dee005aef6b299..d62a7457682eaf2057217b6f48a537a5368cf667 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -79,6 +79,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector &Features, HasPrivileged = true; } else if (Feature == "+aix-small-local-exec-tls") { HasAIXSmallLocalExecTLS = true; + } else if (Feature == "+aix-small-local-dynamic-tls") { + HasAIXSmallLocalDynamicTLS = true; } else if (Feature == "+isa-v206-instructions") { IsISA2_06 = true; } else if (Feature == "+isa-v207-instructions") { @@ -573,9 +575,10 @@ bool PPCTargetInfo::initFeatureMap( // Privileged instructions are off by default. Features["privileged"] = false; - // The code generated by the -maix-small-local-exec-tls option is turned - // off by default. + // The code generated by the -maix-small-local-[exec|dynamic]-tls option is + // turned off by default. Features["aix-small-local-exec-tls"] = false; + Features["aix-small-local-dynamic-tls"] = false; Features["spe"] = llvm::StringSwitch(CPU) .Case("8548", true) @@ -713,6 +716,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("rop-protect", HasROPProtect) .Case("privileged", HasPrivileged) .Case("aix-small-local-exec-tls", HasAIXSmallLocalExecTLS) + .Case("aix-small-local-dynamic-tls", HasAIXSmallLocalDynamicTLS) .Case("isa-v206-instructions", IsISA2_06) .Case("isa-v207-instructions", IsISA2_07) .Case("isa-v30-instructions", IsISA3_0) diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index fa2f442e25846de4ed0386e543a8613a213120b2..60bc1dec8f95c62a21e69f93e2a7cf1a2caa8146 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -61,6 +61,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { bool HasROPProtect = false; bool HasPrivileged = false; bool HasAIXSmallLocalExecTLS = false; + bool HasAIXSmallLocalDynamicTLS = false; bool HasVSX = false; bool UseCRBits = false; bool HasP8Vector = false; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 6cc00b85664f411f860d40d10d049ce99a37a8cb..22c3f8642ad8ebc28a8f4dc5a119d131478f7bd2 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -104,6 +104,21 @@ static cl::opt ClSanitizeOnOptimizerEarlyEP( "sanitizer-early-opt-ep", cl::Optional, cl::desc("Insert sanitizers on OptimizerEarlyEP.")); +// Experiment to mark cold functions as optsize/minsize/optnone. +// TODO: remove once this is exposed as a proper driver flag. +static cl::opt ClPGOColdFuncAttr( + "pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden, + cl::desc( + "Function attribute to apply to cold functions as determined by PGO"), + cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default", + "Default (no attribute)"), + clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize", + "Mark cold functions with optsize."), + clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize", + "Mark cold functions with minsize."), + clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone", + "Mark cold functions with optnone."))); + extern cl::opt ProfileCorrelate; // Re-link builtin bitcodes after optimization @@ -768,42 +783,41 @@ void EmitAssemblyHelper::RunOptimizationPipeline( CodeGenOpts.InstrProfileOutput.empty() ? getDefaultProfileGenName() : CodeGenOpts.InstrProfileOutput, "", "", CodeGenOpts.MemoryProfileUsePath, nullptr, PGOOptions::IRInstr, - PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + PGOOptions::NoCSAction, ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, /*PseudoProbeForProfiling=*/false, CodeGenOpts.AtomicProfileUpdate); else if (CodeGenOpts.hasProfileIRUse()) { // -fprofile-use. auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse : PGOOptions::NoCSAction; - PGOOpt = PGOOptions( - CodeGenOpts.ProfileInstrumentUsePath, "", - CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS, - PGOOptions::IRUse, CSAction, PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling); + PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "", + CodeGenOpts.ProfileRemappingFile, + CodeGenOpts.MemoryProfileUsePath, VFS, + PGOOptions::IRUse, CSAction, ClPGOColdFuncAttr, + CodeGenOpts.DebugInfoForProfiling); } else if (!CodeGenOpts.SampleProfileFile.empty()) // -fprofile-sample-use PGOOpt = PGOOptions( CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::SampleUse, - PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + PGOOptions::NoCSAction, ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling); else if (!CodeGenOpts.MemoryProfileUsePath.empty()) // -fmemory-profile-use (without any of the above options) PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::NoAction, PGOOptions::NoCSAction, - PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling); + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling); else if (CodeGenOpts.PseudoProbeForProfiling) // -fpseudo-probe-for-profiling - PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, - PGOOptions::NoAction, PGOOptions::NoCSAction, - PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling, true); + PGOOpt = + PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, + PGOOptions::NoAction, PGOOptions::NoCSAction, + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, true); else if (CodeGenOpts.DebugInfoForProfiling) // -fdebug-info-for-profiling PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, PGOOptions::NoCSAction, - PGOOptions::ColdFuncOpt::Default, true); + ClPGOColdFuncAttr, true); // Check to see if we want to generate a CS profile. if (CodeGenOpts.hasProfileCSIRInstr()) { @@ -820,14 +834,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline( : CodeGenOpts.InstrProfileOutput; PGOOpt->CSAction = PGOOptions::CSIRInstr; } else - PGOOpt = - PGOOptions("", - CodeGenOpts.InstrProfileOutput.empty() - ? getDefaultProfileGenName() - : CodeGenOpts.InstrProfileOutput, - "", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, - PGOOptions::CSIRInstr, PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling); + PGOOpt = PGOOptions("", + CodeGenOpts.InstrProfileOutput.empty() + ? getDefaultProfileGenName() + : CodeGenOpts.InstrProfileOutput, + "", /*MemoryProfile=*/"", nullptr, + PGOOptions::NoAction, PGOOptions::CSIRInstr, + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling); } if (TM) TM->setPGOOption(PGOOpt); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a05874e63c73c202c87cea797b311dac72b7b24a..7e5f2edfc732cce0c7d0cc309f94b69b71a61a76 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -826,29 +826,32 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField( ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) { const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel(); - unsigned FieldNo = 0; - bool IsUnion = RD->isUnion(); + uint32_t FieldNo = 0; - for (const Decl *D : RD->decls()) { - if (const auto *Field = dyn_cast(D); - Field && (Name.empty() || Field->getNameAsString() == Name) && + if (RD->isImplicit()) + return nullptr; + + for (const FieldDecl *FD : RD->fields()) { + if ((Name.empty() || FD->getNameAsString() == Name) && Decl::isFlexibleArrayMemberLike( - Ctx, Field, Field->getType(), StrictFlexArraysLevel, + Ctx, FD, FD->getType(), StrictFlexArraysLevel, /*IgnoreTemplateOrMacroSubstitution=*/true)) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); Offset += Layout.getFieldOffset(FieldNo); - return Field; + return FD; } - if (const auto *Record = dyn_cast(D)) - if (const FieldDecl *Field = - FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) { + QualType Ty = FD->getType(); + if (Ty->isRecordType()) { + if (const FieldDecl *Field = FindFlexibleArrayMemberField( + Ctx, Ty->getAsRecordDecl(), Name, Offset)) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); Offset += Layout.getFieldOffset(FieldNo); return Field; } + } - if (!IsUnion && isa(D)) + if (!RD->isUnion()) ++FieldNo; } @@ -858,14 +861,13 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField( static unsigned CountCountedByAttrs(const RecordDecl *RD) { unsigned Num = 0; - for (const Decl *D : RD->decls()) { - if (const auto *FD = dyn_cast(D); - FD && FD->getType()->isCountAttributedType()) { + for (const FieldDecl *FD : RD->fields()) { + if (FD->getType()->isCountAttributedType()) return ++Num; - } - if (const auto *Rec = dyn_cast(D)) - Num += CountCountedByAttrs(Rec); + QualType Ty = FD->getType(); + if (Ty->isRecordType()) + Num += CountCountedByAttrs(Ty->getAsRecordDecl()); } return Num; @@ -18265,8 +18267,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, if (!E->getArg(0)->getType()->hasFloatingRepresentation()) llvm_unreachable("lerp operand must have a float representation"); return Builder.CreateIntrinsic( - /*ReturnType=*/X->getType(), Intrinsic::dx_lerp, - ArrayRef{X, Y, S}, nullptr, "dx.lerp"); + /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(), + ArrayRef{X, Y, S}, nullptr, "hlsl.lerp"); } case Builtin::BI__builtin_hlsl_elementwise_frac: { Value *Op0 = EmitScalarExpr(E->getArg(0)); @@ -18294,20 +18296,28 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Value *M = EmitScalarExpr(E->getArg(0)); Value *A = EmitScalarExpr(E->getArg(1)); Value *B = EmitScalarExpr(E->getArg(2)); - if (E->getArg(0)->getType()->hasFloatingRepresentation()) { + if (E->getArg(0)->getType()->hasFloatingRepresentation()) return Builder.CreateIntrinsic( /*ReturnType*/ M->getType(), Intrinsic::fmuladd, - ArrayRef{M, A, B}, nullptr, "dx.fmad"); - } + ArrayRef{M, A, B}, nullptr, "hlsl.fmad"); + if (E->getArg(0)->getType()->hasSignedIntegerRepresentation()) { - return Builder.CreateIntrinsic( - /*ReturnType*/ M->getType(), Intrinsic::dx_imad, - ArrayRef{M, A, B}, nullptr, "dx.imad"); + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil) + return Builder.CreateIntrinsic( + /*ReturnType*/ M->getType(), Intrinsic::dx_imad, + ArrayRef{M, A, B}, nullptr, "dx.imad"); + + Value *Mul = Builder.CreateNSWMul(M, A); + return Builder.CreateNSWAdd(Mul, B); } assert(E->getArg(0)->getType()->hasUnsignedIntegerRepresentation()); - return Builder.CreateIntrinsic( - /*ReturnType=*/M->getType(), Intrinsic::dx_umad, - ArrayRef{M, A, B}, nullptr, "dx.umad"); + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil) + return Builder.CreateIntrinsic( + /*ReturnType=*/M->getType(), Intrinsic::dx_umad, + ArrayRef{M, A, B}, nullptr, "dx.umad"); + + Value *Mul = Builder.CreateNUWMul(M, A); + return Builder.CreateNUWAdd(Mul, B); } case Builtin::BI__builtin_hlsl_elementwise_rcp: { Value *Op0 = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 93ca711f716fce5bec80f56f81e0f3749de5d3f8..567e85a02dc6126fdbf990b50e43743779b2a19e 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -413,10 +413,8 @@ llvm::Function * CodeGenFunction::generateAwaitSuspendWrapper(Twine const &CoroName, Twine const &SuspendPointName, CoroutineSuspendExpr const &S) { - std::string FuncName = "__await_suspend_wrapper_"; - FuncName += CoroName.str(); - FuncName += '_'; - FuncName += SuspendPointName.str(); + std::string FuncName = + (CoroName + ".__await_suspend_wrapper__" + SuspendPointName).str(); ASTContext &C = getContext(); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index c924660c5a91c8ca05303e86ed9576edd0eb57fe..94962091116afbb2927c5ebe4ce81d5497a0e579 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -564,12 +564,13 @@ class ConstStructBuilder { public: static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, - InitListExpr *ILE, QualType StructTy); + const InitListExpr *ILE, + QualType StructTy); static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, const APValue &Value, QualType ValTy); static bool UpdateStruct(ConstantEmitter &Emitter, ConstantAggregateBuilder &Const, CharUnits Offset, - InitListExpr *Updater); + const InitListExpr *Updater); private: ConstStructBuilder(ConstantEmitter &Emitter, @@ -586,7 +587,7 @@ private: bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, llvm::ConstantInt *InitExpr, bool AllowOverwrite = false); - bool Build(InitListExpr *ILE, bool AllowOverwrite); + bool Build(const InitListExpr *ILE, bool AllowOverwrite); bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase, const CXXRecordDecl *VTableClass, CharUnits BaseOffset); llvm::Constant *Finalize(QualType Ty); @@ -635,7 +636,7 @@ bool ConstStructBuilder::AppendBitField( static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, ConstantAggregateBuilder &Const, CharUnits Offset, QualType Type, - InitListExpr *Updater) { + const InitListExpr *Updater) { if (Type->isRecordType()) return ConstStructBuilder::UpdateStruct(Emitter, Const, Offset, Updater); @@ -647,7 +648,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, llvm::Type *ElemTy = Emitter.CGM.getTypes().ConvertTypeForMem(ElemType); llvm::Constant *FillC = nullptr; - if (Expr *Filler = Updater->getArrayFiller()) { + if (const Expr *Filler = Updater->getArrayFiller()) { if (!isa(Filler)) { FillC = Emitter.tryEmitAbstractForMemory(Filler, ElemType); if (!FillC) @@ -658,7 +659,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, unsigned NumElementsToUpdate = FillC ? CAT->getZExtSize() : Updater->getNumInits(); for (unsigned I = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) { - Expr *Init = nullptr; + const Expr *Init = nullptr; if (I < Updater->getNumInits()) Init = Updater->getInit(I); @@ -667,7 +668,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, return false; } else if (!Init || isa(Init)) { continue; - } else if (InitListExpr *ChildILE = dyn_cast(Init)) { + } else if (const auto *ChildILE = dyn_cast(Init)) { if (!EmitDesignatedInitUpdater(Emitter, Const, Offset, ElemType, ChildILE)) return false; @@ -683,7 +684,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, return true; } -bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) { +bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) { RecordDecl *RD = ILE->getType()->castAs()->getDecl(); const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); @@ -711,7 +712,7 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) { // Get the initializer. A struct can include fields without initializers, // we just use explicit null values for them. - Expr *Init = nullptr; + const Expr *Init = nullptr; if (ElementNo < ILE->getNumInits()) Init = ILE->getInit(ElementNo++); if (Init && isa(Init)) @@ -879,7 +880,7 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Type) { } llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, - InitListExpr *ILE, + const InitListExpr *ILE, QualType ValTy) { ConstantAggregateBuilder Const(Emitter.CGM); ConstStructBuilder Builder(Emitter, Const, CharUnits::Zero()); @@ -906,7 +907,8 @@ llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, bool ConstStructBuilder::UpdateStruct(ConstantEmitter &Emitter, ConstantAggregateBuilder &Const, - CharUnits Offset, InitListExpr *Updater) { + CharUnits Offset, + const InitListExpr *Updater) { return ConstStructBuilder(Emitter, Const, Offset) .Build(Updater, /*AllowOverwrite*/ true); } @@ -1013,8 +1015,8 @@ EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType, // // Constant folding is currently missing support for a few features supported // here: CK_ToUnion, CK_ReinterpretMemberPointer, and DesignatedInitUpdateExpr. -class ConstExprEmitter : - public StmtVisitor { +class ConstExprEmitter + : public ConstStmtVisitor { CodeGenModule &CGM; ConstantEmitter &Emitter; llvm::LLVMContext &VMContext; @@ -1027,43 +1029,42 @@ public: // Visitor Methods //===--------------------------------------------------------------------===// - llvm::Constant *VisitStmt(Stmt *S, QualType T) { - return nullptr; - } + llvm::Constant *VisitStmt(const Stmt *S, QualType T) { return nullptr; } - llvm::Constant *VisitConstantExpr(ConstantExpr *CE, QualType T) { + llvm::Constant *VisitConstantExpr(const ConstantExpr *CE, QualType T) { if (llvm::Constant *Result = Emitter.tryEmitConstantExpr(CE)) return Result; return Visit(CE->getSubExpr(), T); } - llvm::Constant *VisitParenExpr(ParenExpr *PE, QualType T) { + llvm::Constant *VisitParenExpr(const ParenExpr *PE, QualType T) { return Visit(PE->getSubExpr(), T); } llvm::Constant * - VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE, + VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *PE, QualType T) { return Visit(PE->getReplacement(), T); } - llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE, + llvm::Constant *VisitGenericSelectionExpr(const GenericSelectionExpr *GE, QualType T) { return Visit(GE->getResultExpr(), T); } - llvm::Constant *VisitChooseExpr(ChooseExpr *CE, QualType T) { + llvm::Constant *VisitChooseExpr(const ChooseExpr *CE, QualType T) { return Visit(CE->getChosenSubExpr(), T); } - llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E, QualType T) { + llvm::Constant *VisitCompoundLiteralExpr(const CompoundLiteralExpr *E, + QualType T) { return Visit(E->getInitializer(), T); } - llvm::Constant *VisitCastExpr(CastExpr *E, QualType destType) { + llvm::Constant *VisitCastExpr(const CastExpr *E, QualType destType) { if (const auto *ECE = dyn_cast(E)) CGM.EmitExplicitCastExprType(ECE, Emitter.CGF); - Expr *subExpr = E->getSubExpr(); + const Expr *subExpr = E->getSubExpr(); switch (E->getCastKind()) { case CK_ToUnion: { @@ -1117,7 +1118,8 @@ public: // interesting conversions should be done in Evaluate(). But as a // special case, allow compound literals to support the gcc extension // allowing "struct x {int x;} x = (struct x) {};". - if (auto *E = dyn_cast(subExpr->IgnoreParens())) + if (const auto *E = + dyn_cast(subExpr->IgnoreParens())) return Visit(E->getInitializer(), destType); return nullptr; } @@ -1232,21 +1234,22 @@ public: llvm_unreachable("Invalid CastKind"); } - llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE, QualType T) { + llvm::Constant *VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *DIE, + QualType T) { // No need for a DefaultInitExprScope: we don't handle 'this' in a // constant expression. return Visit(DIE->getExpr(), T); } - llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E, QualType T) { + llvm::Constant *VisitExprWithCleanups(const ExprWithCleanups *E, QualType T) { return Visit(E->getSubExpr(), T); } - llvm::Constant *VisitIntegerLiteral(IntegerLiteral *I, QualType T) { + llvm::Constant *VisitIntegerLiteral(const IntegerLiteral *I, QualType T) { return llvm::ConstantInt::get(CGM.getLLVMContext(), I->getValue()); } - llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) { + llvm::Constant *EmitArrayInitialization(const InitListExpr *ILE, QualType T) { auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType()); assert(CAT && "can't emit array init for non-constant-bound array"); unsigned NumInitElements = ILE->getNumInits(); @@ -1260,7 +1263,7 @@ public: // Initialize remaining array elements. llvm::Constant *fillC = nullptr; - if (Expr *filler = ILE->getArrayFiller()) { + if (const Expr *filler = ILE->getArrayFiller()) { fillC = Emitter.tryEmitAbstractForMemory(filler, EltType); if (!fillC) return nullptr; @@ -1275,7 +1278,7 @@ public: llvm::Type *CommonElementType = nullptr; for (unsigned i = 0; i < NumInitableElts; ++i) { - Expr *Init = ILE->getInit(i); + const Expr *Init = ILE->getInit(i); llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType); if (!C) return nullptr; @@ -1292,16 +1295,17 @@ public: fillC); } - llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) { + llvm::Constant *EmitRecordInitialization(const InitListExpr *ILE, + QualType T) { return ConstStructBuilder::BuildStruct(Emitter, ILE, T); } - llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E, + llvm::Constant *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E, QualType T) { return CGM.EmitNullConstant(T); } - llvm::Constant *VisitInitListExpr(InitListExpr *ILE, QualType T) { + llvm::Constant *VisitInitListExpr(const InitListExpr *ILE, QualType T) { if (ILE->isTransparent()) return Visit(ILE->getInit(0), T); @@ -1314,8 +1318,9 @@ public: return nullptr; } - llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E, - QualType destType) { + llvm::Constant * + VisitDesignatedInitUpdateExpr(const DesignatedInitUpdateExpr *E, + QualType destType) { auto C = Visit(E->getBase(), destType); if (!C) return nullptr; @@ -1329,12 +1334,13 @@ public: llvm::Type *ValTy = CGM.getTypes().ConvertType(destType); bool HasFlexibleArray = false; - if (auto *RT = destType->getAs()) + if (const auto *RT = destType->getAs()) HasFlexibleArray = RT->getDecl()->hasFlexibleArrayMember(); return Const.build(ValTy, HasFlexibleArray); } - llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E, QualType Ty) { + llvm::Constant *VisitCXXConstructExpr(const CXXConstructExpr *E, + QualType Ty) { if (!E->getConstructor()->isTrivial()) return nullptr; @@ -1344,13 +1350,13 @@ public: assert(E->getConstructor()->isCopyOrMoveConstructor() && "trivial ctor has argument but isn't a copy/move ctor"); - Expr *Arg = E->getArg(0); + const Expr *Arg = E->getArg(0); assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) && "argument to copy ctor is of wrong type"); // Look through the temporary; it's just converting the value to an // lvalue to pass it to the constructor. - if (auto *MTE = dyn_cast(Arg)) + if (const auto *MTE = dyn_cast(Arg)) return Visit(MTE->getSubExpr(), Ty); // Don't try to support arbitrary lvalue-to-rvalue conversions for now. return nullptr; @@ -1359,12 +1365,12 @@ public: return CGM.EmitNullConstant(Ty); } - llvm::Constant *VisitStringLiteral(StringLiteral *E, QualType T) { + llvm::Constant *VisitStringLiteral(const StringLiteral *E, QualType T) { // This is a string literal initializing an array in an initializer. return CGM.GetConstantArrayFromStringLiteral(E); } - llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E, QualType T) { + llvm::Constant *VisitObjCEncodeExpr(const ObjCEncodeExpr *E, QualType T) { // This must be an @encode initializing an array in a static initializer. // Don't emit it as the address of the string, emit the string data itself // as an inline array. @@ -1383,14 +1389,14 @@ public: return Visit(E->getSubExpr(), T); } - llvm::Constant *VisitUnaryMinus(UnaryOperator *U, QualType T) { + llvm::Constant *VisitUnaryMinus(const UnaryOperator *U, QualType T) { if (llvm::Constant *C = Visit(U->getSubExpr(), T)) if (auto *CI = dyn_cast(C)) return llvm::ConstantInt::get(CGM.getLLVMContext(), -CI->getValue()); return nullptr; } - llvm::Constant *VisitPackIndexingExpr(PackIndexingExpr *E, QualType T) { + llvm::Constant *VisitPackIndexingExpr(const PackIndexingExpr *E, QualType T) { return Visit(E->getSelectedExpr(), T); } @@ -1696,8 +1702,7 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { if (!destType->isReferenceType()) { QualType nonMemoryDestType = getNonMemoryType(CGM, destType); - if (llvm::Constant *C = ConstExprEmitter(*this).Visit(const_cast(E), - nonMemoryDestType)) + if (llvm::Constant *C = ConstExprEmitter(*this).Visit(E, nonMemoryDestType)) return emitForMemory(C, destType); } @@ -1777,8 +1782,7 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E, assert(!destType->isVoidType() && "can't emit a void constant"); if (!destType->isReferenceType()) - if (llvm::Constant *C = - ConstExprEmitter(*this).Visit(const_cast(E), destType)) + if (llvm::Constant *C = ConstExprEmitter(*this).Visit(E, destType)) return C; Expr::EvalResult Result; @@ -2022,7 +2026,7 @@ ConstantLValue ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { assert(E->isExpressibleAsConstantInitializer() && "this boxed expression can't be emitted as a compile-time constant"); - auto *SL = cast(E->getSubExpr()->IgnoreParenCasts()); + const auto *SL = cast(E->getSubExpr()->IgnoreParenCasts()); return emitConstantObjCStringLiteral(SL, E->getType(), CGM); } @@ -2048,12 +2052,12 @@ ConstantLValueEmitter::VisitCallExpr(const CallExpr *E) { builtin != Builtin::BI__builtin___NSStringMakeConstantString) return nullptr; - auto literal = cast(E->getArg(0)->IgnoreParenCasts()); + const auto *Literal = cast(E->getArg(0)->IgnoreParenCasts()); if (builtin == Builtin::BI__builtin___NSStringMakeConstantString) { - return CGM.getObjCRuntime().GenerateConstantString(literal); + return CGM.getObjCRuntime().GenerateConstantString(Literal); } else { // FIXME: need to deal with UCN conversion issues. - return CGM.GetAddrOfConstantCFString(literal); + return CGM.GetAddrOfConstantCFString(Literal); } } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index c76052ff6280f98dab14f366f6952e24cbad7633..40a5cd20c3d715a343f1e44866000641be07d5c4 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1540,7 +1540,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, if (auto DstPT = dyn_cast(DstTy)) { // The source value may be an integer, or a pointer. if (isa(SrcTy)) - return Builder.CreateBitCast(Src, DstTy, "conv"); + return Src; assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); // First, convert to the correct width so that we control the kind of diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 506b364f5b2ec7110399dee74a54c195930cc9cc..0abe39dedcb96f81a5f5b3d62ca5aaf103936727 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -74,6 +74,7 @@ public: GENERATE_HLSL_INTRINSIC_FUNCTION(All, all) GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any) + GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp) GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id) //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 64c39c5de351c7a2f2fffed3809ac75b482f79d3..733686d4946b3c1e529d80d11e5e9e743c6ed6b7 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1208,6 +1208,12 @@ struct CounterCoverageMappingBuilder /// Find a valid gap range between \p AfterLoc and \p BeforeLoc. std::optional findGapAreaBetween(SourceLocation AfterLoc, SourceLocation BeforeLoc) { + // Some statements (like AttributedStmt and ImplicitValueInitExpr) don't + // have valid source locations. Do not emit a gap region if this is the case + // in either AfterLoc end or BeforeLoc end. + if (AfterLoc.isInvalid() || BeforeLoc.isInvalid()) + return std::nullopt; + // If AfterLoc is in function-like macro, use the right parenthesis // location. if (AfterLoc.isMacroID()) { @@ -1368,9 +1374,8 @@ struct CounterCoverageMappingBuilder for (const Stmt *Child : S->children()) if (Child) { // If last statement contains terminate statements, add a gap area - // between the two statements. Skipping attributed statements, because - // they don't have valid start location. - if (LastStmt && HasTerminateStmt && !isa(Child)) { + // between the two statements. + if (LastStmt && HasTerminateStmt) { auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child)); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp index 77c89356bc76bb38a4b0771b739b281a92bb709f..8cc82a0ee7168729ccd39eedff8de7df5b32cd3c 100644 --- a/clang/lib/Driver/OffloadBundler.cpp +++ b/clang/lib/Driver/OffloadBundler.cpp @@ -1010,6 +1010,10 @@ CompressedOffloadBundle::compress(llvm::compression::Params P, uint16_t CompressionMethod = static_cast(P.format); uint32_t UncompressedSize = Input.getBuffer().size(); + uint32_t TotalFileSize = MagicNumber.size() + sizeof(TotalFileSize) + + sizeof(Version) + sizeof(CompressionMethod) + + sizeof(UncompressedSize) + sizeof(TruncatedHash) + + CompressedBuffer.size(); SmallVector FinalBuffer; llvm::raw_svector_ostream OS(FinalBuffer); @@ -1017,6 +1021,8 @@ CompressedOffloadBundle::compress(llvm::compression::Params P, OS.write(reinterpret_cast(&Version), sizeof(Version)); OS.write(reinterpret_cast(&CompressionMethod), sizeof(CompressionMethod)); + OS.write(reinterpret_cast(&TotalFileSize), + sizeof(TotalFileSize)); OS.write(reinterpret_cast(&UncompressedSize), sizeof(UncompressedSize)); OS.write(reinterpret_cast(&TruncatedHash), @@ -1034,6 +1040,8 @@ CompressedOffloadBundle::compress(llvm::compression::Params P, (UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds; llvm::errs() << "Compressed bundle format version: " << Version << "\n" + << "Total file size (including headers): " + << formatWithCommas(TotalFileSize) << " bytes\n" << "Compression method used: " << MethodUsed << "\n" << "Compression level: " << P.level << "\n" << "Binary size before compression: " @@ -1059,9 +1067,9 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, StringRef Blob = Input.getBuffer(); - if (Blob.size() < HeaderSize) { + if (Blob.size() < V1HeaderSize) return llvm::MemoryBuffer::getMemBufferCopy(Blob); - } + if (llvm::identify_magic(Blob) != llvm::file_magic::offload_bundle_compressed) { if (Verbose) @@ -1069,21 +1077,32 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, return llvm::MemoryBuffer::getMemBufferCopy(Blob); } + size_t CurrentOffset = MagicSize; + uint16_t ThisVersion; + memcpy(&ThisVersion, Blob.data() + CurrentOffset, sizeof(uint16_t)); + CurrentOffset += VersionFieldSize; + uint16_t CompressionMethod; + memcpy(&CompressionMethod, Blob.data() + CurrentOffset, sizeof(uint16_t)); + CurrentOffset += MethodFieldSize; + + uint32_t TotalFileSize; + if (ThisVersion >= 2) { + if (Blob.size() < V2HeaderSize) + return createStringError(inconvertibleErrorCode(), + "Compressed bundle header size too small"); + memcpy(&TotalFileSize, Blob.data() + CurrentOffset, sizeof(uint32_t)); + CurrentOffset += FileSizeFieldSize; + } + uint32_t UncompressedSize; + memcpy(&UncompressedSize, Blob.data() + CurrentOffset, sizeof(uint32_t)); + CurrentOffset += UncompressedSizeFieldSize; + uint64_t StoredHash; - memcpy(&ThisVersion, Input.getBuffer().data() + MagicNumber.size(), - sizeof(uint16_t)); - memcpy(&CompressionMethod, Blob.data() + MagicSize + VersionFieldSize, - sizeof(uint16_t)); - memcpy(&UncompressedSize, - Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize, - sizeof(uint32_t)); - memcpy(&StoredHash, - Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize + - SizeFieldSize, - sizeof(uint64_t)); + memcpy(&StoredHash, Blob.data() + CurrentOffset, sizeof(uint64_t)); + CurrentOffset += HashFieldSize; llvm::compression::Format CompressionFormat; if (CompressionMethod == @@ -1102,7 +1121,7 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, DecompressTimer.startTimer(); SmallVector DecompressedData; - StringRef CompressedData = Blob.substr(HeaderSize); + StringRef CompressedData = Blob.substr(CurrentOffset); if (llvm::Error DecompressionError = llvm::compression::decompress( CompressionFormat, llvm::arrayRefFromStringRef(CompressedData), DecompressedData, UncompressedSize)) @@ -1135,8 +1154,11 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, double DecompressionSpeedMBs = (UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds; - llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n" - << "Decompression method: " + llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n"; + if (ThisVersion >= 2) + llvm::errs() << "Total file size (from header): " + << formatWithCommas(TotalFileSize) << " bytes\n"; + llvm::errs() << "Decompression method: " << (CompressionFormat == llvm::compression::Format::Zlib ? "zlib" : "zstd") diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 8bfe9f02a091d17a01c3c4c4fd48d38c50a25dca..6a4f2548c0bffaf98e4488b3a138dc9f78f833b5 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1192,7 +1192,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, BinaryMetadataIgnorelistFiles); } - if (TC.getTriple().isOSWindows() && needsUbsanRt()) { + if (TC.getTriple().isOSWindows() && needsUbsanRt() && + Args.hasFlag(options::OPT_frtlib_defaultlib, + options::OPT_fno_rtlib_defaultlib, true)) { // Instruct the code generator to embed linker directives in the object file // that cause the required runtime libraries to be linked. CmdArgs.push_back( @@ -1203,7 +1205,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, "--dependent-lib=" + TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx"))); } - if (TC.getTriple().isOSWindows() && needsStatsRt()) { + if (TC.getTriple().isOSWindows() && needsStatsRt() && + Args.hasFlag(options::OPT_frtlib_defaultlib, + options::OPT_fno_rtlib_defaultlib, true)) { CmdArgs.push_back(Args.MakeArgString( "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client"))); diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp index 5ffe73236205d3b2ef166ba71cf69052e85055a7..634c096523319d8d5b4f0a61dba9945f8177f578 100644 --- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp @@ -125,21 +125,22 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, bool UseSeparateSections = isUseSeparateSections(Triple); bool HasDefaultDataSections = Triple.isOSBinFormatXCOFF(); - if (Args.hasArg(options::OPT_maix_small_local_exec_tls)) { + if (Args.hasArg(options::OPT_maix_small_local_exec_tls) || + Args.hasArg(options::OPT_maix_small_local_dynamic_tls)) { if (!Triple.isOSAIX() || !Triple.isArch64Bit()) - D.Diag(diag::err_opt_not_valid_on_target) << "-maix-small-local-exec-tls"; + D.Diag(diag::err_opt_not_valid_on_target) + << "-maix-small-local-[exec|dynamic]-tls"; - // The -maix-small-local-exec-tls option should only be used with + // The -maix-small-local-[exec|dynamic]-tls option should only be used with // -fdata-sections, as having data sections turned off with this option - // is not ideal for performance. Moreover, the small-local-exec-tls region - // is a limited resource, and should not be used for variables that may - // be replaced. + // is not ideal for performance. Moreover, the + // small-local-[exec|dynamic]-tls region is a limited resource, and should + // not be used for variables that may be replaced. if (!Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, UseSeparateSections || HasDefaultDataSections)) D.Diag(diag::err_drv_argument_only_allowed_with) - << "-maix-small-local-exec-tls" - << "-fdata-sections"; + << "-maix-small-local-[exec|dynamic]-tls" << "-fdata-sections"; } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 456ea74caadb009b01e87583aec0272e125d8195..e7ccf9a23e7eda2dc7b4866fc7feeddbef054202 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -637,7 +637,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, ProfileGenerateArg->getValue())); // The default is to use Clang Instrumentation. CmdArgs.push_back("-fprofile-instrument=clang"); - if (TC.getTriple().isWindowsMSVCEnvironment()) { + if (TC.getTriple().isWindowsMSVCEnvironment() && + Args.hasFlag(options::OPT_frtlib_defaultlib, + options::OPT_fno_rtlib_defaultlib, true)) { // Add dependent lib for clang_rt.profile CmdArgs.push_back(Args.MakeArgString( "--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile"))); @@ -656,7 +658,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, CmdArgs.push_back("-fprofile-instrument=csllvm"); } if (PGOGenArg) { - if (TC.getTriple().isWindowsMSVCEnvironment()) { + if (TC.getTriple().isWindowsMSVCEnvironment() && + Args.hasFlag(options::OPT_frtlib_defaultlib, + options::OPT_fno_rtlib_defaultlib, true)) { // Add dependent lib for clang_rt.profile CmdArgs.push_back(Args.MakeArgString( "--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile"))); @@ -847,6 +851,16 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_O_Group)) RelaxDefault = A->getOption().matches(options::OPT_O0); + // RISC-V requires an indirect jump for offsets larger than 1MiB. This cannot + // be done by assembler branch relaxation as it needs a free temporary + // register. Because of this, branch relaxation is handled by a MachineIR + // pass before the assembler. Forcing assembler branch relaxation for -O0 + // makes the MachineIR branch relaxation inaccurate and it will miss cases + // where an indirect branch is necessary. To avoid this issue we are + // sacrificing the compile time improvement of using -mrelax-all for -O0. + if (C.getDefaultToolChain().getTriple().isRISCV()) + RelaxDefault = false; + if (RelaxDefault) { RelaxDefault = false; for (const auto &Act : C.getActions()) { @@ -4634,7 +4648,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, // Emit DW_TAG_template_alias for template aliases? True by default for SCE. bool UseDebugTemplateAlias = - DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 5; + DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 4; if (const auto *DebugTemplateAlias = Args.getLastArg( options::OPT_gtemplate_alias, options::OPT_gno_template_alias)) { // DW_TAG_template_alias is only supported from DWARFv5 but if a user @@ -4733,7 +4747,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, Output.getFilename()); } -static void ProcessVSRuntimeLibrary(const ArgList &Args, +static void ProcessVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { unsigned RTOptionID = options::OPT__SLASH_MT; @@ -4796,6 +4810,12 @@ static void ProcessVSRuntimeLibrary(const ArgList &Args, // implemented in clang. CmdArgs.push_back("--dependent-lib=oldnames"); } + + // All Arm64EC object files implicitly add softintrin.lib. This is necessary + // even if the file doesn't actually refer to any of the routines because + // the CRT itself has incomplete dependency markings. + if (TC.getTriple().isWindowsArm64EC()) + CmdArgs.push_back("--dependent-lib=softintrin"); } void Clang::ConstructJob(Compilation &C, const JobAction &JA, @@ -7051,7 +7071,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() && Args.hasArg(options::OPT_fms_runtime_lib_EQ)) - ProcessVSRuntimeLibrary(Args, CmdArgs); + ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs); // Handle -fgcc-version, if present. VersionTuple GNUCVer; @@ -8178,7 +8198,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, ArgStringList &CmdArgs) const { bool isNVPTX = getToolChain().getTriple().isNVPTX(); - ProcessVSRuntimeLibrary(Args, CmdArgs); + ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs); if (Arg *ShowIncludes = Args.getLastArg(options::OPT__SLASH_showIncludes, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index b46bac24503ce1c64cfa0fa0c51a07164a986600..abe0b931676005c00de472e432051db124f6785d 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -118,7 +118,7 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const { Arg *gNArg = Args.getLastArg(options::OPT_gN_Group); DebugInfoKind = debugLevelToInfoKind(*gNArg); } else if (Args.hasArg(options::OPT_g_Flag)) { - DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly; + DebugInfoKind = llvm::codegenoptions::FullDebugInfo; } else { DebugInfoKind = llvm::codegenoptions::NoDebugInfo; } diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 57f966c8b2be35def3a2b0ca408d6c52e79a07cb..8b1dcb4a4144f4044a1f7f8e7c3cb6204c2834a1 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -164,27 +164,29 @@ std::optional serializeAvailability(const AvailabilityInfo &Avail) { if (Avail.isDefault()) return std::nullopt; - Object Availability; Array AvailabilityArray; - Availability["domain"] = Avail.Domain; - serializeObject(Availability, "introduced", - serializeSemanticVersion(Avail.Introduced)); - serializeObject(Availability, "deprecated", - serializeSemanticVersion(Avail.Deprecated)); - serializeObject(Availability, "obsoleted", - serializeSemanticVersion(Avail.Obsoleted)); + if (Avail.isUnconditionallyDeprecated()) { Object UnconditionallyDeprecated; UnconditionallyDeprecated["domain"] = "*"; UnconditionallyDeprecated["isUnconditionallyDeprecated"] = true; AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated)); } - if (Avail.isUnconditionallyUnavailable()) { - Object UnconditionallyUnavailable; - UnconditionallyUnavailable["domain"] = "*"; - UnconditionallyUnavailable["isUnconditionallyUnavailable"] = true; - AvailabilityArray.emplace_back(std::move(UnconditionallyUnavailable)); + Object Availability; + + Availability["domain"] = Avail.Domain; + + if (Avail.isUnavailable()) { + Availability["isUnconditionallyUnavailable"] = true; + } else { + serializeObject(Availability, "introduced", + serializeSemanticVersion(Avail.Introduced)); + serializeObject(Availability, "deprecated", + serializeSemanticVersion(Avail.Deprecated)); + serializeObject(Availability, "obsoleted", + serializeSemanticVersion(Avail.Obsoleted)); } + AvailabilityArray.emplace_back(std::move(Availability)); return AvailabilityArray; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a679683077ac949e38ce55dc388fe9256977535b..cdfb4256e41d93ddf36de11fb047aeb4fdc37eb0 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1543,6 +1543,7 @@ private: return false; if (Line.MustBeDeclaration && Contexts.size() == 1 && !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) && + !Line.startsWith(tok::l_paren) && !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) { if (const auto *Previous = Tok->Previous; !Previous || @@ -2726,8 +2727,10 @@ private: } } - if (Tok.Next->isOneOf(tok::question, tok::ampamp)) + if (Tok.Next->is(tok::question) || + (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(IsCpp))) { return false; + } // `foreach((A a, B b) in someList)` should not be seen as a cast. if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp()) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5531e938e0f4f4f9fa2e48f39caedfd21d1052b6..8236051e30c4a5daa74b8ae09ce7e77d286cfad9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3660,6 +3660,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, case LangOptions::ClangABI::Ver17: GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0"); break; + case LangOptions::ClangABI::Ver18: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0"); + break; case LangOptions::ClangABI::Latest: break; } @@ -4167,6 +4170,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.setClangABICompat(LangOptions::ClangABI::Ver15); else if (Major <= 17) Opts.setClangABICompat(LangOptions::ClangABI::Ver17); + else if (Major <= 18) + Opts.setClangABICompat(LangOptions::ClangABI::Ver18); } else if (Ver != "latest") { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); diff --git a/clang/lib/Headers/avxintrin.h b/clang/lib/Headers/avxintrin.h index be7a0b247e03d45d7e7429de4dce85546b87206b..4983f3311370014f773499e784560fbd19eb2b46 100644 --- a/clang/lib/Headers/avxintrin.h +++ b/clang/lib/Headers/avxintrin.h @@ -840,6 +840,7 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c) /// Copies the values stored in a 128-bit vector of [4 x float] as /// specified by the 128-bit integer vector operand. +/// /// \headerfile /// /// This intrinsic corresponds to the VPERMILPS instruction. diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5eec2a2fd6d1a69c76a3464997394b681cb133a6..ef90fe9e6f5451701d6b2fd01639c70cad9839bc 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -209,6 +209,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, if (Err) return; CI->ExecuteAction(*Act); + + if (getCodeGen()) + CachedInCodeGenModule = GenModule(); + std::unique_ptr IncrConsumer = std::make_unique(Interp, CI->takeASTConsumer()); CI->setASTConsumer(std::move(IncrConsumer)); @@ -224,11 +228,8 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, return; // PTU.takeError(); } - if (CodeGenerator *CG = getCodeGen()) { - std::unique_ptr M(CG->ReleaseModule()); - CG->StartModule("incr_module_" + std::to_string(PTUs.size()), - M->getContext()); - PTU->TheModule = std::move(M); + if (getCodeGen()) { + PTU->TheModule = GenModule(); assert(PTU->TheModule && "Failed to create initial PTU"); } } @@ -364,6 +365,19 @@ IncrementalParser::Parse(llvm::StringRef input) { std::unique_ptr IncrementalParser::GenModule() { static unsigned ID = 0; if (CodeGenerator *CG = getCodeGen()) { + // Clang's CodeGen is designed to work with a single llvm::Module. In many + // cases for convenience various CodeGen parts have a reference to the + // llvm::Module (TheModule or Module) which does not change when a new + // module is pushed. However, the execution engine wants to take ownership + // of the module which does not map well to CodeGen's design. To work this + // around we created an empty module to make CodeGen happy. We should make + // sure it always stays empty. + assert((!CachedInCodeGenModule || + (CachedInCodeGenModule->empty() && + CachedInCodeGenModule->global_empty() && + CachedInCodeGenModule->alias_empty() && + CachedInCodeGenModule->ifunc_empty())) && + "CodeGen wrote to a readonly module"); std::unique_ptr M(CG->ReleaseModule()); CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); return M; diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index e13b74c7f6594890ac6481e4be41a2270086bac7..f63bce50acd3b90b1964963add99fa5c23861744 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -24,6 +24,7 @@ #include namespace llvm { class LLVMContext; +class Module; } // namespace llvm namespace clang { @@ -57,6 +58,10 @@ protected: /// of code. std::list PTUs; + /// When CodeGen is created the first llvm::Module gets cached in many places + /// and we must keep it alive. + std::unique_ptr CachedInCodeGenModule; + IncrementalParser(); public: diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 438c6d772e6e04d41412dfbb018f651f9c9a2e7a..9c0cbea5052cb23dcb781c8d3ac72653506f1daf 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -974,6 +974,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, bool isFixedPointConstant = isFixedPointLiteral(); bool isFPConstant = isFloatingLiteral(); bool HasSize = false; + bool DoubleUnderscore = false; // Loop over all of the characters of the suffix. If we see something bad, // we break out of the loop. @@ -1117,6 +1118,31 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (isImaginary) break; // Cannot be repeated. isImaginary = true; continue; // Success. + case '_': + if (isFPConstant) + break; // Invalid for floats + if (HasSize) + break; + if (DoubleUnderscore) + break; // Cannot be repeated. + if (LangOpts.CPlusPlus && s + 2 < ThisTokEnd && + s[1] == '_') { // s + 2 < ThisTokEnd to ensure some character exists + // after __ + DoubleUnderscore = true; + s += 2; // Skip both '_' + if (s + 1 < ThisTokEnd && + (*s == 'u' || *s == 'U')) { // Ensure some character after 'u'/'U' + isUnsigned = true; + ++s; + } + if (s + 1 < ThisTokEnd && + ((*s == 'w' && *(++s) == 'b') || (*s == 'W' && *(++s) == 'B'))) { + isBitInt = true; + HasSize = true; + continue; + } + } + break; case 'w': case 'W': if (isFPConstant) @@ -1127,9 +1153,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // wb and WB are allowed, but a mixture of cases like Wb or wB is not. We // explicitly do not support the suffix in C++ as an extension because a // library-based UDL that resolves to a library type may be more - // appropriate there. - if (!LangOpts.CPlusPlus && ((s[0] == 'w' && s[1] == 'b') || - (s[0] == 'W' && s[1] == 'B'))) { + // appropriate there. The same rules apply for __wb/__WB. + if ((!LangOpts.CPlusPlus || DoubleUnderscore) && s + 1 < ThisTokEnd && + ((s[0] == 'w' && s[1] == 'b') || (s[0] == 'W' && s[1] == 'B'))) { isBitInt = true; HasSize = true; ++s; // Skip both characters (2nd char skipped on continue). @@ -1241,7 +1267,9 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, return false; // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid. - if (Suffix[0] == '_') + // Suffixes starting with '__' (double underscore) are for use by + // the implementation. + if (Suffix.starts_with("_") && !Suffix.starts_with("__")) return true; // In C++11, there are no library suffixes. diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp index 8f25c67ec9dfbe40d1e73c9ac2efff1fb2b5d846..f267efabd617fd9cfaad99c1d998adc593588be8 100644 --- a/clang/lib/Lex/PPExpressions.cpp +++ b/clang/lib/Lex/PPExpressions.cpp @@ -333,11 +333,11 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, : diag::ext_cxx23_size_t_suffix : diag::err_cxx23_size_t_suffix); - // 'wb/uwb' literals are a C23 feature. We explicitly do not support the - // suffix in C++ as an extension because a library-based UDL that resolves - // to a library type may be more appropriate there. + // 'wb/uwb' literals are a C23 feature. + // '__wb/__uwb' are a C++ extension. if (Literal.isBitInt) - PP.Diag(PeekTok, PP.getLangOpts().C23 + PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix + : PP.getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix : diag::ext_c23_bitint_suffix); diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index d054eda279b8c874b50c6844fc7dd2b593e77b80..a26568dfd6aae39f7c6546714c3c16ac2e6554f6 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -603,6 +603,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { // to be re-used for method bodies as well. ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope); + Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); + Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); if (Tok.is(tok::kw_try)) { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 5f26b5a9e46befd4069ff325d6a301079df5fafe..05ad5ecbfaa0cff6e311750f7499d848e9c17b6e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2222,7 +2222,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } if (getLangOpts().HLSL) - MaybeParseHLSLSemantics(D); + MaybeParseHLSLAnnotations(D); if (Tok.is(tok::kw_requires)) ParseTrailingRequiresClause(D); @@ -2469,7 +2469,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, ParseDeclarator(D); if (getLangOpts().HLSL) - MaybeParseHLSLSemantics(D); + MaybeParseHLSLAnnotations(D); if (!D.isInvalidType()) { // C++2a [dcl.decl]p1 @@ -7699,7 +7699,7 @@ void Parser::ParseParameterDeclarationClause( // Parse GNU attributes, if present. MaybeParseGNUAttributes(ParmDeclarator); if (getLangOpts().HLSL) - MaybeParseHLSLSemantics(DS.getAttributes()); + MaybeParseHLSLAnnotations(DS.getAttributes()); if (Tok.is(tok::kw_requires)) { // User tried to define a requires clause in a parameter declaration, diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index d97985d42369ad9626a31ff83f725af40a4bf4b9..f4cbece31f1810fab9d81f96da4d44661739c499 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -63,7 +63,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { SourceLocation IdentifierLoc = ConsumeToken(); ParsedAttributes Attrs(AttrFactory); - MaybeParseHLSLSemantics(Attrs, nullptr); + MaybeParseHLSLAnnotations(Attrs, nullptr); ParseScope BufferScope(this, Scope::DeclScope); BalancedDelimiterTracker T(*this, tok::l_brace); @@ -118,12 +118,10 @@ static void fixSeparateAttrArgAndNumber(StringRef ArgStr, SourceLocation ArgLoc, Slot = IdentifierLoc::create(Ctx, ArgLoc, PP.getIdentifierInfo(FixedArg)); } -void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs, - SourceLocation *EndLoc) { - // FIXME: HLSLSemantic is shared for Semantic and resource binding which is - // confusing. Need a better name to avoid misunderstanding. Issue - // https://github.com/llvm/llvm-project/issues/57882 - assert(Tok.is(tok::colon) && "Not a HLSL Semantic"); +void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs, + SourceLocation *EndLoc) { + + assert(Tok.is(tok::colon) && "Not a HLSL Annotation"); ConsumeToken(); IdentifierInfo *II = nullptr; @@ -141,7 +139,7 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs, if (EndLoc) *EndLoc = Tok.getLocation(); ParsedAttr::Kind AttrKind = - ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLSemantic); + ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLAnnotation); ArgsVector ArgExprs; switch (AttrKind) { @@ -192,10 +190,10 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs, case ParsedAttr::AT_HLSLSV_DispatchThreadID: break; default: - llvm_unreachable("invalid HLSL Semantic"); + llvm_unreachable("invalid HLSL Annotation"); break; } Attrs.addNew(II, Loc, nullptr, SourceLocation(), ArgExprs.data(), - ArgExprs.size(), ParsedAttr::Form::HLSLSemantic()); + ArgExprs.size(), ParsedAttr::Form::HLSLAnnotation()); } diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 671dcb71e51a376285a97af5568ccf8b233b2ebf..8e54fe012c55d7074b677783a88994c31bc8d5e4 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -3736,6 +3736,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) | Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope); + Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); // Tell the actions module that we have entered a method or c-function definition // with the specified Declarator for the method/function. diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 757417f75c9636e53444875dbc38c1f677ef1fc6..8a18fca8064ee119ae2d429844eb41021b93cc72 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -632,16 +632,54 @@ Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { return Clauses; } -ExprResult Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, - OpenACCClauseKind CK, - SourceLocation Loc) { - ExprResult ER = - getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); +Parser::OpenACCIntExprParseResult +Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + SourceLocation Loc) { + ExprResult ER = ParseAssignmentExpression(); + // If the actual parsing failed, we don't know the state of the parse, so + // don't try to continue. if (!ER.isUsable()) - return ER; + return {ER, OpenACCParseCanContinue::Cannot}; + + // Parsing can continue after the initial assignment expression parsing, so + // even if there was a typo, we can continue. + ER = getActions().CorrectDelayedTyposInExpr(ER); + if (!ER.isUsable()) + return {ER, OpenACCParseCanContinue::Can}; + + return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()), + OpenACCParseCanContinue::Can}; +} + +bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, + OpenACCClauseKind CK, SourceLocation Loc, + llvm::SmallVectorImpl &IntExprs) { + OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc); + + if (!CurResult.first.isUsable() && + CurResult.second == OpenACCParseCanContinue::Cannot) { + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return true; + } + + IntExprs.push_back(CurResult.first.get()); + + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + ExpectAndConsume(tok::comma); + + CurResult = ParseOpenACCIntExpr(DK, CK, Loc); - return getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()); + if (!CurResult.first.isUsable() && + CurResult.second == OpenACCParseCanContinue::Cannot) { + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return true; + } + IntExprs.push_back(CurResult.first.get()); + } + return false; } bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { @@ -761,7 +799,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { ConsumeToken(); return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, GangLoc) - .isInvalid(); + .first.isInvalid(); } if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) && @@ -773,7 +811,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { // This is just the 'num' case where 'num' is optional. return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, GangLoc) - .isInvalid(); + .first.isInvalid(); } bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) { @@ -946,13 +984,25 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( } break; } - case OpenACCClauseKind::NumGangs: + case OpenACCClauseKind::NumGangs: { + llvm::SmallVector IntExprs; + + if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid, + OpenACCClauseKind::NumGangs, ClauseLoc, + IntExprs)) { + Parens.skipToEnd(); + return OpenACCCanContinue(); + } + ParsedClause.setIntExprDetails(std::move(IntExprs)); + break; + } case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::VectorLength: { ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, - ClauseKind, ClauseLoc); + ClauseKind, ClauseLoc) + .first; if (IntExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); @@ -1017,7 +1067,8 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( : OpenACCSpecialTokenKind::Num, ClauseKind); ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, - ClauseKind, ClauseLoc); + ClauseKind, ClauseLoc) + .first; if (IntExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); @@ -1081,11 +1132,13 @@ bool Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) { // Consume colon. ConsumeToken(); - ExprResult IntExpr = ParseOpenACCIntExpr( - IsDirective ? OpenACCDirectiveKind::Wait - : OpenACCDirectiveKind::Invalid, - IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, - Loc); + ExprResult IntExpr = + ParseOpenACCIntExpr(IsDirective ? OpenACCDirectiveKind::Wait + : OpenACCDirectiveKind::Invalid, + IsDirective ? OpenACCClauseKind::Invalid + : OpenACCClauseKind::Wait, + Loc) + .first; if (IntExpr.isInvalid()) return true; diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index b07ce451e878eb3a3d9a17a3b5db9c6c8f52e6e7..665253a6674d27add53478667a99269212ac8f02 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -733,7 +733,12 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { // we introduce the type parameter into the local scope. SourceLocation EqualLoc; ParsedType DefaultArg; + std::optional DontDestructTemplateIds; if (TryConsumeToken(tok::equal, EqualLoc)) { + // The default argument might contain a lambda declaration; avoid destroying + // parsed template ids at the end of that declaration because they can be + // used in a type constraint later. + DontDestructTemplateIds.emplace(*this, /*DelayTemplateIdDestruction=*/true); // The default argument may declare template parameters, notably // if it contains a generic lambda, so we need to increase // the template depth as these parameters would not be instantiated diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index ef46fc74cedc14da01ca0e528ed3619b2c356a5c..adcbe5858bc78ee76c511c697df15b904973f549 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1497,6 +1497,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return Actions.ActOnFinishFunctionBody(Res, nullptr, false); } + Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 058e22cb2b814e6d4f53c801662ff71311f04d5f..6a5f9f6680e640972990384cfe01661d4a5eb959 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -46,7 +46,7 @@ void MultiplexExternalSemaSource::AddSource(ExternalSemaSource *Source) { // ExternalASTSource. //===----------------------------------------------------------------------===// -Decl *MultiplexExternalSemaSource::GetExternalDecl(uint32_t ID) { +Decl *MultiplexExternalSemaSource::GetExternalDecl(Decl::DeclID ID) { for(size_t i = 0; i < Sources.size(); ++i) if (Decl *Result = Sources[i]->GetExternalDecl(ID)) return Result; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 73e76e05a0d9d152ead9c13adeb0837060604553..51757f4cf727d6433144bf664637a3b9900f0da9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7953,6 +7953,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // For variadic functions, we may have more args than parameters. // For some K&R functions, we may have less args than parameters. const auto N = std::min(Proto->getNumParams(), Args.size()); + bool AnyScalableArgsOrRet = Proto->getReturnType()->isSizelessVectorType(); for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. if (const Expr *Arg = Args[ArgIdx]) { @@ -7966,6 +7967,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, checkAIXMemberAlignment((Arg->getExprLoc()), Arg); QualType ParamTy = Proto->getParamType(ArgIdx); + if (ParamTy->isSizelessVectorType()) + AnyScalableArgsOrRet = true; QualType ArgTy = Arg->getType(); CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1), ArgTy, ParamTy); @@ -7986,6 +7989,23 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } } + // If the call requires a streaming-mode change and has scalable vector + // arguments or return values, then warn the user that the streaming and + // non-streaming vector lengths may be different. + const auto *CallerFD = dyn_cast(CurContext); + if (CallerFD && (!FD || !FD->getBuiltinID()) && AnyScalableArgsOrRet) { + bool IsCalleeStreaming = + ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask; + bool IsCalleeStreamingCompatible = + ExtInfo.AArch64SMEAttributes & + FunctionType::SME_PStateSMCompatibleMask; + ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); + if (!IsCalleeStreamingCompatible && + (CallerFnType == ArmStreamingCompatible || + ((CallerFnType == ArmStreaming) ^ IsCalleeStreaming))) + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); + } + FunctionType::ArmStateValue CalleeArmZAState = FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes); FunctionType::ArmStateValue CalleeArmZT0State = @@ -7994,7 +8014,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, CalleeArmZT0State != FunctionType::ARM_None) { bool CallerHasZAState = false; bool CallerHasZT0State = false; - if (const auto *CallerFD = dyn_cast(CurContext)) { + if (CallerFD) { auto *Attr = CallerFD->getAttr(); if (Attr && Attr->isNewZA()) CallerHasZAState = true; @@ -12759,10 +12779,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // In this case, the expression could be printed using a different // specifier, but we've decided that the specifier is probably correct // and we should cast instead. Just use the normal warning message. + + unsigned Diag = + IsScopedEnum + ? diag::warn_format_conversion_argument_type_mismatch_pedantic + : diag::warn_format_conversion_argument_type_mismatch; + EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum - << E->getSourceRange(), + S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy + << IsEnum << E->getSourceRange(), E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints); } } diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 736632857efc36997d039c0037e7ffdbe1e88b98..81334c817b2af2edf716413938db94e059ca67e8 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -817,13 +817,10 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) { assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); const auto &Functions = Operators.asUnresolvedSet(); - bool IsOverloaded = - Functions.size() > 1 || - (Functions.size() == 1 && isa(*Functions.begin())); Expr *CoawaitOp = UnresolvedLookupExpr::Create( Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), - DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded, - Functions.begin(), Functions.end()); + DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(), + Functions.end(), /*KnownDependent=*/false); assert(CoawaitOp); return CoawaitOp; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index af6b3f21f15a65878de26a9b376bd073beca5682..452e00fa32b10208a3ce638f4f501eecd818af85 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1240,8 +1240,8 @@ Corrected: Result.suppressDiagnostics(); return NameClassification::OverloadSet(UnresolvedLookupExpr::Create( Context, Result.getNamingClass(), SS.getWithLocInContext(Context), - Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(), - Result.begin(), Result.end())); + Result.getLookupNameInfo(), ADL, Result.begin(), Result.end(), + /*KnownDependent=*/false)); } ExprResult @@ -12408,12 +12408,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } // Check if the function definition uses any AArch64 SME features without - // having the '+sme' feature enabled. + // having the '+sme' feature enabled and warn user if sme locally streaming + // function returns or uses arguments with VL-based types. if (DeclIsDefn) { const auto *Attr = NewFD->getAttr(); bool UsesSM = NewFD->hasAttr(); bool UsesZA = Attr && Attr->isNewZA(); bool UsesZT0 = Attr && Attr->isNewZT0(); + + if (NewFD->hasAttr()) { + if (NewFD->getReturnType()->isSizelessVectorType() || + llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) { + return P->getOriginalType()->isSizelessVectorType(); + })) + Diag(NewFD->getLocation(), + diag::warn_sme_locally_streaming_has_vl_args_returns); + } if (const auto *FPT = NewFD->getType()->getAs()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); UsesSM |= @@ -15889,6 +15899,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, FD->setInvalidDecl(); return D; } + + // Some function attributes (like OptimizeNoneAttr) need actions before + // parsing body started. + applyFunctionAttributesBeforeParsingBody(D); + // We want to attach documentation to original Decl (which might be // a function template). ActOnDocumentableDecl(D); @@ -15900,6 +15915,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, return D; } +void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) { + if (!FD || FD->isInvalidDecl()) + return; + if (auto *TD = dyn_cast(FD)) + FD = TD->getTemplatedDecl(); + if (FD && FD->hasAttr()) { + FPOptionsOverride FPO; + FPO.setDisallowOptimizations(); + CurFPFeatures.applyChanges(FPO); + FpPragmaStack.CurrentValue = + CurFPFeatures.getChangesFrom(FPOptions(LangOpts)); + } +} + /// Given the set of return statements within a function body, /// compute the variables that are subject to the named return value /// optimization. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2ef8a15d5238fa1610d1246383f724aab594474f..abdbc9d8830c03f6c70121e73f9f2427450cc577 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1302,7 +1302,7 @@ static bool checkTupleLikeDecomposition(Sema &S, // in the associated namespaces. Expr *Get = UnresolvedLookupExpr::Create( S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), - DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/ true, &Args, + DeclarationNameInfo(GetDN, Loc), /*RequiresADL=*/true, &Args, UnresolvedSetIterator(), UnresolvedSetIterator(), /*KnownDependent=*/false); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 74d6f0700b0e4f52e79864564426133328a0e723..934ba174a426e4362ddebe6e8e9d66a528d7eda7 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -494,6 +494,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { } } } + + // Some function attributes (like OptimizeNoneAttr) need actions before + // parsing body started. + applyFunctionAttributesBeforeParsingBody(D); } namespace { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2c444d3f8dc484ad8a9c8cbb3af25577efcfcbcb..5c861467bc1023dc85dba17e56d5fdafc2fa6fc3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2918,26 +2918,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. - if (getLangOpts().CPlusPlus && !R.empty() && - (*R.begin())->isCXXClassMember()) { - bool MightBeImplicitMember; - if (!IsAddressOfOperand) - MightBeImplicitMember = true; - else if (!SS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa(R.getFoundDecl()) || - isa(R.getFoundDecl()) || - isa(R.getFoundDecl()); - - if (MightBeImplicitMember) - return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, - R, TemplateArgs, S); - } + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + S); if (TemplateArgs || TemplateKWLoc.isValid()) { @@ -3471,12 +3454,10 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // we've picked a target. R.suppressDiagnostics(); - UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - SS.getWithLocInContext(Context), - R.getLookupNameInfo(), - NeedsADL, R.isOverloadedResult(), - R.begin(), R.end()); + UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create( + Context, R.getNamingClass(), SS.getWithLocInContext(Context), + R.getLookupNameInfo(), NeedsADL, R.begin(), R.end(), + /*KnownDependent=*/false); return ULE; } @@ -4156,11 +4137,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // 'wb/uwb' literals are a C23 feature. We support _BitInt as a type in C++, // but we do not currently support the suffix in C++ mode because it's not // entirely clear whether WG21 will prefer this suffix to return a library - // type such as std::bit_int instead of returning a _BitInt. - if (Literal.isBitInt && !getLangOpts().CPlusPlus) - PP.Diag(Tok.getLocation(), getLangOpts().C23 - ? diag::warn_c23_compat_bitint_suffix - : diag::ext_c23_bitint_suffix); + // type such as std::bit_int instead of returning a _BitInt. '__wb/__uwb' + // literals are a C++ extension. + if (Literal.isBitInt) + PP.Diag(Tok.getLocation(), + getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix + : getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix + : diag::ext_c23_bitint_suffix); // Get the value in the widest-possible width. What is "widest" depends on // whether the literal is a bit-precise integer or not. For a bit-precise diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7582cbd75fec052abc66f28b322a869f37aa5b23..779a41620033dc6a6cef9d3f7b694a654f6a061a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1416,26 +1416,42 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, } ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { - /// C++ 9.3.2: In the body of a non-static member function, the keyword this - /// is a non-lvalue expression whose value is the address of the object for - /// which the function is called. + // C++20 [expr.prim.this]p1: + // The keyword this names a pointer to the object for which an + // implicit object member function is invoked or a non-static + // data member's initializer is evaluated. QualType ThisTy = getCurrentThisType(); - if (ThisTy.isNull()) { - DeclContext *DC = getFunctionLevelDeclContext(); + if (CheckCXXThisType(Loc, ThisTy)) + return ExprError(); - if (const auto *Method = dyn_cast(DC); - Method && Method->isExplicitObjectMemberFunction()) { - return Diag(Loc, diag::err_invalid_this_use) << 1; - } + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); +} - if (isLambdaCallWithExplicitObjectParameter(CurContext)) - return Diag(Loc, diag::err_invalid_this_use) << 1; +bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) { + if (!Type.isNull()) + return false; - return Diag(Loc, diag::err_invalid_this_use) << 0; + // C++20 [expr.prim.this]p3: + // If a declaration declares a member function or member function template + // of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" wherever X is the current class between + // the optional cv-qualifier-seq and the end of the function-definition, + // member-declarator, or declarator. It shall not appear within the + // declaration of either a static member function or an explicit object + // member function of the current class (although its type and value + // category are defined within such member functions as they are within + // an implicit object member function). + DeclContext *DC = getFunctionLevelDeclContext(); + if (const auto *Method = dyn_cast(DC); + Method && Method->isExplicitObjectMemberFunction()) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else if (isLambdaCallWithExplicitObjectParameter(CurContext)) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else { + Diag(Loc, diag::err_invalid_this_use) << 0; } - - return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); + return true; } Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, @@ -8644,21 +8660,8 @@ static ExprResult attemptRecovery(Sema &SemaRef, // Detect and handle the case where the decl might be an implicit // member. - bool MightBeImplicitMember; - if (!Consumer.isAddressOfOperand()) - MightBeImplicitMember = true; - else if (!NewSS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa(ND) || - isa(ND) || - isa(ND); - - if (MightBeImplicitMember) + if (SemaRef.isPotentialImplicitMemberAccess( + NewSS, R, Consumer.isAddressOfOperand())) return SemaRef.BuildPossibleImplicitMemberExpr( NewSS, /*TemplateKWLoc*/ SourceLocation(), R, /*TemplateArgs*/ nullptr, /*S*/ nullptr); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index c79128bc8f39e7e97b5273511d6b05f67224aaa2..6e30716b9ae436b3eacec19f76a974734d116a9a 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -62,6 +62,10 @@ enum IMAKind { /// The reference is a contextually-permitted abstract member reference. IMA_Abstract, + /// Whether the context is static is dependent on the enclosing template (i.e. + /// in a dependent class scope explicit specialization). + IMA_Dependent, + /// The reference may be to an unresolved using declaration and the /// context is not an instance method. IMA_Unresolved_StaticOrExplicitContext, @@ -92,14 +96,25 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); - bool isStaticOrExplicitContext = - SemaRef.CXXThisTypeOverride.isNull() && - (!isa(DC) || cast(DC)->isStatic() || - cast(DC)->isExplicitObjectMemberFunction()); + bool couldInstantiateToStatic = false; + bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull(); - if (R.isUnresolvableResult()) + if (auto *MD = dyn_cast(DC)) { + if (MD->isImplicitObjectMemberFunction()) { + isStaticOrExplicitContext = false; + // A dependent class scope function template explicit specialization + // that is neither declared 'static' nor with an explicit object + // parameter could instantiate to a static or non-static member function. + couldInstantiateToStatic = MD->getDependentSpecializationInfo(); + } + } + + if (R.isUnresolvableResult()) { + if (couldInstantiateToStatic) + return IMA_Dependent; return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext : IMA_Unresolved; + } // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; @@ -124,6 +139,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; + if (couldInstantiateToStatic) + return IMA_Dependent; + // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static // member function of a class can only be used: @@ -264,21 +282,37 @@ static void diagnoseInstanceReference(Sema &SemaRef, } } +bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, + LookupResult &R, + bool IsAddressOfOperand) { + if (!getLangOpts().CPlusPlus) + return false; + else if (R.empty() || !R.begin()->isCXXClassMember()) + return false; + else if (!IsAddressOfOperand) + return true; + else if (!SS.isEmpty()) + return false; + else if (R.isOverloadedResult()) + return false; + else if (R.isUnresolvableResult()) + return true; + else + return isa(R.getFoundDecl()); +} + /// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE) { - switch (ClassifyImplicitMemberAccess(*this, R)) { + const TemplateArgumentListInfo *TemplateArgs, const Scope *S) { + switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) { case IMA_Instance: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); - case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false, - S); - + return BuildImplicitMemberExpr( + SS, TemplateKWLoc, R, TemplateArgs, + /*IsKnownInstance=*/Classification == IMA_Instance, S); case IMA_Field_Uneval_Context: Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) << R.getLookupNameInfo().getName(); @@ -288,8 +322,16 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr( case IMA_Mixed_StaticOrExplicitContext: case IMA_Unresolved_StaticOrExplicitContext: if (TemplateArgs || TemplateKWLoc.isValid()) - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); - return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false, + TemplateArgs); + return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false, + /*AcceptInvalidDecl=*/false); + case IMA_Dependent: + R.suppressDiagnostics(); + return UnresolvedLookupExpr::Create( + Context, R.getNamingClass(), SS.getWithLocInContext(Context), + TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false, + TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true); case IMA_Error_StaticOrExplicitContext: case IMA_Error_Unrelated: diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 190739fa02e9327ad43d16ac3ecbd4e366e719c7..ba69e71e30a181f855f3015c870a201675b37768 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -91,6 +91,7 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, default: return false; } + case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::VectorLength: switch (DirectiveKind) { @@ -230,6 +231,40 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getConditionExpr(), Clause.getEndLoc()); } + case OpenACCClauseKind::NumGangs: { + // Restrictions only properly implemented on 'compute' constructs, and + // 'compute' constructs are the only construct that can do anything with + // this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + break; + + // There is no prose in the standard that says duplicates aren't allowed, + // but this diagnostic is present in other compilers, as well as makes + // sense. + if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause)) + return nullptr; + + if (Clause.getIntExprs().empty()) + Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args) + << /*NoArgs=*/0; + + unsigned MaxArgs = + (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel || + Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) + ? 3 + : 1; + if (Clause.getIntExprs().size() > MaxArgs) + Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args) + << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs + << Clause.getIntExprs().size(); + + // Create the AST node for the clause even if the number of expressions is + // incorrect. + return OpenACCNumGangsClause::Create( + getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), + Clause.getIntExprs(), Clause.getEndLoc()); + break; + } case OpenACCClauseKind::NumWorkers: { // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 3e9f6cba25076d1ccd7b35c000a539e5460642ed..5ba09926acf2b9e92c9eb3bcfc29b004d1fdebd3 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -19354,7 +19354,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, return UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, - /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end()); + /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false); } // Lookup inside the classes. // C++ [over.match.oper]p3: @@ -22220,7 +22220,7 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, return UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId, - /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end()); + /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false); } SourceLocation Loc = MapperId.getLoc(); // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 48d6264029e9bfe900c7c62f2eac399cc1d0661c..04cd9e78739d209b176d8cc5aba80fe87a440762 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14261,20 +14261,14 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, OverloadResult, AllowTypoCorrection); } -static bool IsOverloaded(const UnresolvedSetImpl &Functions) { - return Functions.size() > 1 || - (Functions.size() == 1 && - isa((*Functions.begin())->getUnderlyingDecl())); -} - ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, NestedNameSpecifierLoc NNSLoc, DeclarationNameInfo DNI, const UnresolvedSetImpl &Fns, bool PerformADL) { return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI, - PerformADL, IsOverloaded(Fns), - Fns.begin(), Fns.end()); + PerformADL, Fns.begin(), Fns.end(), + /*KnownDependent=*/false); } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 7cd494b42250d4d66bc77357b6a24e32021cb1e6..9d44c22c8ddcc3a234c46af72b16d19e96829d4f 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -109,7 +109,7 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable); } else if (PragmaName == "unroll") { // #pragma unroll N - if (ValueExpr) { + if (ValueExpr && !ValueExpr->isValueDependent()) { llvm::APSInt ValueAPS; ExprResult R = S.VerifyIntegerConstantExpression(ValueExpr, &ValueAPS); assert(!R.isInvalid() && "unroll count value must be a valid value, it's " diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d4976f9d0d11d81e8b06f7321034bef56403243b..4bda31ba67c02d03e1d9323fdef4d3e763ca871c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2962,19 +2962,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getCanonicalTemplateArgument( Context.getInjectedTemplateArg(NewParam)); } - // Substitute new template parameters into requires-clause if present. - Expr *RequiresClause = - transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); - // FIXME: implement the is_deducible constraint per C++ - // [over.match.class.deduct]p3.3: - // ... and a constraint that is satisfied if and only if the arguments - // of A are deducible (see below) from the return type. - auto *FPrimeTemplateParamList = TemplateParameterList::Create( - Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), - AliasTemplate->getTemplateParameters()->getLAngleLoc(), - FPrimeTemplateParams, - AliasTemplate->getTemplateParameters()->getRAngleLoc(), - /*RequiresClause=*/RequiresClause); // To form a deduction guide f' from f, we leverage clang's instantiation // mechanism, we construct a template argument list where the template @@ -3020,6 +3007,20 @@ void DeclareImplicitDeductionGuidesForTypeAlias( F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), Sema::CodeSynthesisContext::BuildingDeductionGuides)) { auto *GG = cast(FPrime); + // Substitute new template parameters into requires-clause if present. + Expr *RequiresClause = + transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); + // FIXME: implement the is_deducible constraint per C++ + // [over.match.class.deduct]p3.3: + // ... and a constraint that is satisfied if and only if the arguments + // of A are deducible (see below) from the return type. + auto *FPrimeTemplateParamList = TemplateParameterList::Create( + Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), + AliasTemplate->getTemplateParameters()->getLAngleLoc(), + FPrimeTemplateParams, + AliasTemplate->getTemplateParameters()->getRAngleLoc(), + /*RequiresClause=*/RequiresClause); + buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList, GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), GG->getTypeSourceInfo(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3e6676f21c9be09a8c29c1c2c41a0be54289d3f3..98d5c7cb3a8a808d203ccd97e07614c5bad7e60d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2502,10 +2502,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, assert(Arg.getKind() == TemplateArgument::Type && "unexpected nontype template argument kind in template rewrite"); QualType NewT = Arg.getAsType(); - assert(isa(NewT) && - "type parm not rewritten to type parm"); - auto NewTL = TLB.push(NewT); - NewTL.setNameLoc(TL.getNameLoc()); + TLB.pushTrivial(SemaRef.Context, NewT, TL.getNameLoc()); return NewT; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index caa07abb61fe349b91ec5aeb101dde2da5725328..787a485e0b2f8c36f9526e3d3f2b5728e68329a6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5101,6 +5101,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + Qualifiers ThisTypeQuals; + CXXRecordDecl *ThisContext = nullptr; + if (CXXMethodDecl *Method = dyn_cast(Function)) { + ThisContext = Method->getParent(); + ThisTypeQuals = Method->getMethodQualifiers(); + } + CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals); + // Introduce a new scope where local variable instantiations will be // recorded, unless we're actually a member function within a local // class, in which case we need to merge our results with the parent diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 4909414c0c78d44851e609bbdee99e4ccc213d5e..a4b681ae4f008ec81c6f967fe8935f4080109a9c 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1085,9 +1085,11 @@ ExprResult Sema::ActOnPackIndexingExpr(Scope *S, Expr *PackExpression, SourceLocation RSquareLoc) { bool isParameterPack = ::isParameterPack(PackExpression); if (!isParameterPack) { - CorrectDelayedTyposInExpr(IndexExpr); - Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack) - << PackExpression; + if (!PackExpression->containsErrors()) { + CorrectDelayedTyposInExpr(IndexExpr); + Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack) + << PackExpression; + } return ExprError(); } ExprResult Res = diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index ade33ec65038fdb3abc6b10708aec3f7a898163b..539a18eb92a7ce324d5788acf6b91d60b20594c1 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -796,6 +796,9 @@ public: ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI); + ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, + bool IsAddressOfOperand); + StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S); // FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous @@ -3320,12 +3323,13 @@ public: /// Build a new C++ "this" expression. /// - /// By default, builds a new "this" expression without performing any - /// semantic analysis. Subclasses may override this routine to provide - /// different behavior. + /// By default, performs semantic analysis to build a new "this" expression. + /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { + if (getSema().CheckCXXThisType(ThisLoc, ThisType)) + return ExprError(); return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit); } @@ -4759,8 +4763,6 @@ public: const TemplateArgumentLoc *operator->() const { return &Arg; } }; - TemplateArgumentLocInventIterator() { } - explicit TemplateArgumentLocInventIterator(TreeTransform &Self, InputIterator Iter) : Self(Self), Iter(Iter) { } @@ -10429,12 +10431,11 @@ TreeTransform::TransformOMPReductionClause(OMPReductionClause *C) { cast(getDerived().TransformDecl(E->getExprLoc(), D)); Decls.addDecl(InstD, InstD->getAccess()); } - UnresolvedReductions.push_back( - UnresolvedLookupExpr::Create( + UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, - ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), - NameInfo, /*ADL=*/true, ULE->isOverloaded(), - Decls.begin(), Decls.end())); + ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, + /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10480,7 +10481,8 @@ OMPClause *TreeTransform::TransformOMPTaskReductionClause( UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, - /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end())); + /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10525,7 +10527,8 @@ TreeTransform::TransformOMPInReductionClause(OMPInReductionClause *C) { UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, - /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end())); + /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10706,8 +10709,8 @@ bool transformOMPMappableExprListClause( UnresolvedMappers.push_back(UnresolvedLookupExpr::Create( TT.getSema().Context, /*NamingClass=*/nullptr, MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context), - MapperIdInfo, /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), - Decls.end())); + MapperIdInfo, /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else { UnresolvedMappers.push_back(nullptr); } @@ -11159,6 +11162,32 @@ void OpenACCClauseTransform::VisitSelfClause( ParsedClause.getEndLoc()); } +template +void OpenACCClauseTransform::VisitNumGangsClause( + const OpenACCNumGangsClause &C) { + llvm::SmallVector InstantiatedIntExprs; + + for (Expr *CurIntExpr : C.getIntExprs()) { + ExprResult Res = Self.TransformExpr(CurIntExpr); + + if (!Res.isUsable()) + return; + + Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid, + C.getClauseKind(), + C.getBeginLoc(), Res.get()); + if (!Res.isUsable()) + return; + + InstantiatedIntExprs.push_back(Res.get()); + } + + ParsedClause.setIntExprDetails(InstantiatedIntExprs); + NewClause = OpenACCNumGangsClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getIntExprs(), + ParsedClause.getEndLoc()); +} template void OpenACCClauseTransform::VisitNumWorkersClause( const OpenACCNumWorkersClause &C) { @@ -11467,7 +11496,11 @@ template ExprResult TreeTransform::TransformAddressOfOperand(Expr *E) { if (DependentScopeDeclRefExpr *DRE = dyn_cast(E)) - return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr); + return getDerived().TransformDependentScopeDeclRefExpr( + DRE, /*IsAddressOfOperand=*/true, nullptr); + else if (UnresolvedLookupExpr *ULE = dyn_cast(E)) + return getDerived().TransformUnresolvedLookupExpr( + ULE, /*IsAddressOfOperand=*/true); else return getDerived().TransformExpr(E); } @@ -12910,6 +12943,19 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { ArraySize = NewArraySize.get(); } + // Per C++0x [expr.new]p5, the type being constructed may be a + // typedef of an array type. + QualType AllocType = AllocTypeInfo->getType(); + if (ArraySize && E->isTypeDependent()) { + if (const ConstantArrayType *Array = + SemaRef.Context.getAsConstantArrayType(AllocType)) { + ArraySize = IntegerLiteral::Create(SemaRef.Context, Array->getSize(), + SemaRef.Context.getSizeType(), + E->getBeginLoc()); + AllocType = Array->getElementType(); + } + } + // Transform the placement arguments (if any). bool ArgumentChanged = false; SmallVector PlacementArgs; @@ -12971,7 +13017,6 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { return E; } - QualType AllocType = AllocTypeInfo->getType(); if (!ArraySize) { // If no array size was specified, but the new expression was // instantiated with an array type (e.g., "new T" where T is @@ -13174,10 +13219,16 @@ bool TreeTransform::TransformOverloadExprDecls(OverloadExpr *Old, return false; } -template +template +ExprResult TreeTransform::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old) { + return TransformUnresolvedLookupExpr(Old, /*IsAddressOfOperand=*/false); +} + +template ExprResult -TreeTransform::TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *Old) { +TreeTransform::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, + bool IsAddressOfOperand) { LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), Sema::LookupOrdinaryName); @@ -13209,26 +13260,8 @@ TreeTransform::TransformUnresolvedLookupExpr( R.setNamingClass(NamingClass); } + // Rebuild the template arguments, if any. SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); - - // If we have neither explicit template arguments, nor the template keyword, - // it's a normal declaration name or member reference. - if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) { - NamedDecl *D = R.getAsSingle(); - // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an - // instance member. In other contexts, BuildPossibleImplicitMemberExpr will - // give a good diagnostic. - if (D && D->isCXXInstanceMember()) { - return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, - /*TemplateArgs=*/nullptr, - /*Scope=*/nullptr); - } - - return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); - } - - // If we have template arguments, rebuild them, then rebuild the - // templateid expression. TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); if (Old->hasExplicitTemplateArgs() && getDerived().TransformTemplateArguments(Old->getTemplateArgs(), @@ -13238,6 +13271,23 @@ TreeTransform::TransformUnresolvedLookupExpr( return ExprError(); } + // An UnresolvedLookupExpr can refer to a class member. This occurs e.g. when + // a non-static data member is named in an unevaluated operand, or when + // a member is named in a dependent class scope function template explicit + // specialization that is neither declared static nor with an explicit object + // parameter. + if (SemaRef.isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return SemaRef.BuildPossibleImplicitMemberExpr( + SS, TemplateKWLoc, R, + Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr, + /*S=*/nullptr); + + // If we have neither explicit template arguments, nor the template keyword, + // it's a normal declaration name or member reference. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + + // If we have template arguments, then rebuild the template-id expression. return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R, Old->requiresADL(), &TransArgs); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 44e23919ea18e0aea165d30555fd4728869ec612..43b69045bb05436ff9e086f8992a8189eb91fae1 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -954,14 +954,16 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, // Load instance methods for (unsigned I = 0; I != NumInstanceMethods; ++I) { if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs( - F, endian::readNext(d))) + F, + LocalDeclID(endian::readNext(d)))) Result.Instance.push_back(Method); } // Load factory methods for (unsigned I = 0; I != NumFactoryMethods; ++I) { if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs( - F, endian::readNext(d))) + F, + LocalDeclID(endian::readNext(d)))) Result.Factory.push_back(Method); } @@ -1088,10 +1090,11 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // Read all of the declarations visible at global scope with this // name. if (DataLen > 0) { - SmallVector DeclIDs; - for (; DataLen > 0; DataLen -= 4) + SmallVector DeclIDs; + for (; DataLen > 0; DataLen -= sizeof(DeclID)) DeclIDs.push_back(Reader.getGlobalDeclID( - F, endian::readNext(d))); + F, + LocalDeclID(endian::readNext(d)))); Reader.SetGloballyVisibleDecls(II, DeclIDs); } @@ -1211,8 +1214,8 @@ void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type, data_type_builder &Val) { using namespace llvm::support; - for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) { - uint32_t LocalID = endian::readNext(d); + for (unsigned NumDecls = DataLen / sizeof(DeclID); NumDecls; --NumDecls) { + LocalDeclID LocalID(endian::readNext(d)); Val.insert(Reader.getGlobalDeclID(F, LocalID)); } } @@ -1259,9 +1262,8 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, if (!Lex.first) { Lex = std::make_pair( &M, llvm::ArrayRef( - reinterpret_cast( - Blob.data()), - Blob.size() / 4)); + reinterpret_cast(Blob.data()), + Blob.size() / sizeof(DeclID))); } DC->setHasExternalLexicalStorage(true); return false; @@ -1270,7 +1272,7 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, BitstreamCursor &Cursor, uint64_t Offset, - DeclID ID) { + GlobalDeclID ID) { assert(Offset != 0); SavedStreamPosition SavedPosition(Cursor); @@ -1653,7 +1655,7 @@ bool ASTReader::ReadSLocEntry(int ID) { unsigned NumFileDecls = Record[7]; if (NumFileDecls && ContextObj) { - const DeclID *FirstDecl = F->FileSortedDecls + Record[6]; + const LocalDeclID *FirstDecl = F->FileSortedDecls + Record[6]; assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); FileDeclIDs[FID] = FileDeclsInfo(F, llvm::ArrayRef(FirstDecl, NumFileDecls)); @@ -3369,8 +3371,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, if (F.LocalNumDecls > 0) { // Introduce the global -> local mapping for declarations within this // module. - GlobalDeclMap.insert( - std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F)); + GlobalDeclMap.insert(std::make_pair( + GlobalDeclID(getTotalNumDecls() + NUM_PREDEF_DECL_IDS), &F)); // Introduce the local -> global mapping for declarations within this // module. @@ -3389,9 +3391,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case TU_UPDATE_LEXICAL: { DeclContext *TU = ContextObj->getTranslationUnitDecl(); LexicalContents Contents( - reinterpret_cast( - Blob.data()), - static_cast(Blob.size() / 4)); + reinterpret_cast(Blob.data()), + static_cast(Blob.size() / sizeof(DeclID))); TULexicalDecls.push_back(std::make_pair(&F, Contents)); TU->setHasExternalLexicalStorage(true); break; @@ -3399,7 +3400,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case UPDATE_VISIBLE: { unsigned Idx = 0; - serialization::DeclID ID = ReadDeclID(F, Record, Idx); + GlobalDeclID ID = ReadDeclID(F, Record, Idx); auto *Data = (const unsigned char*)Blob.data(); PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&F, Data}); // If we've already loaded the decl, perform the updates when we finish @@ -3460,7 +3461,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, // FIXME: Skip reading this record if our ASTConsumer doesn't care // about "interesting" decls (for instance, if we're building a module). for (unsigned I = 0, N = Record.size(); I != N; ++I) - EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); + EagerlyDeserializedDecls.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case MODULAR_CODEGEN_DECLS: @@ -3469,7 +3471,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, if (F.Kind == MK_MainFile || getContext().getLangOpts().BuildingPCHWithObjectFile) for (unsigned I = 0, N = Record.size(); I != N; ++I) - EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); + EagerlyDeserializedDecls.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case SPECIAL_TYPES: @@ -3501,12 +3504,14 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case UNUSED_FILESCOPED_DECLS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I])); + UnusedFileScopedDecls.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case DELEGATING_CTORS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I])); + DelegatingCtorDecls.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case WEAK_UNDECLARED_IDENTIFIERS: @@ -3614,7 +3619,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case FILE_SORTED_DECLS: - F.FileSortedDecls = (const DeclID *)Blob.data(); + F.FileSortedDecls = (const LocalDeclID *)Blob.data(); F.NumFileSortedDecls = Record[0]; break; @@ -3669,7 +3674,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case EXT_VECTOR_DECLS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I])); + ExtVectorDecls.push_back(getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case VTABLE_USES: @@ -3683,18 +3688,14 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, VTableUses.clear(); for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) { - VTableUses.push_back(getGlobalDeclID(F, Record[Idx++])); VTableUses.push_back( - ReadSourceLocation(F, Record, Idx).getRawEncoding()); - VTableUses.push_back(Record[Idx++]); + {getGlobalDeclID(F, LocalDeclID(Record[Idx++])), + ReadSourceLocation(F, Record, Idx).getRawEncoding(), + (bool)Record[Idx++]}); } break; case PENDING_IMPLICIT_INSTANTIATIONS: - if (PendingInstantiations.size() % 2 != 0) - return llvm::createStringError( - std::errc::illegal_byte_sequence, - "Invalid existing PendingInstantiations"); if (Record.size() % 2 != 0) return llvm::createStringError( @@ -3702,9 +3703,9 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, "Invalid PENDING_IMPLICIT_INSTANTIATIONS block"); for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++])); PendingInstantiations.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); + {getGlobalDeclID(F, LocalDeclID(Record[I++])), + ReadSourceLocation(F, Record, I).getRawEncoding()}); } break; @@ -3713,7 +3714,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, return llvm::createStringError(std::errc::illegal_byte_sequence, "Invalid SEMA_DECL_REFS block"); for (unsigned I = 0, N = Record.size(); I != N; ++I) - SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); + SemaDeclRefs.push_back(getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case PPD_ENTITIES_OFFSETS: { @@ -3772,7 +3773,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, std::errc::illegal_byte_sequence, "invalid DECL_UPDATE_OFFSETS block in AST file"); for (unsigned I = 0, N = Record.size(); I != N; I += 2) { - GlobalDeclID ID = getGlobalDeclID(F, Record[I]); + GlobalDeclID ID = getGlobalDeclID(F, LocalDeclID(Record[I])); DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1])); // If we've already loaded the decl, perform the updates when we finish @@ -3790,7 +3791,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, "invalid DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD block in AST " "file"); for (unsigned I = 0, N = Record.size(); I != N; I += 3) { - GlobalDeclID ID = getGlobalDeclID(F, Record[I]); + GlobalDeclID ID = getGlobalDeclID(F, LocalDeclID(Record[I])); uint64_t BaseOffset = F.DeclsBlockStartOffset; assert(BaseOffset && "Invalid DeclsBlockStartOffset for module file!"); @@ -3825,7 +3826,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, // FIXME: Modules will have trouble with this. CUDASpecialDeclRefs.clear(); for (unsigned I = 0, N = Record.size(); I != N; ++I) - CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I])); + CUDASpecialDeclRefs.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case HEADER_SEARCH_TABLE: @@ -3866,32 +3868,30 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case TENTATIVE_DEFINITIONS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I])); + TentativeDefinitions.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case KNOWN_NAMESPACES: for (unsigned I = 0, N = Record.size(); I != N; ++I) - KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); + KnownNamespaces.push_back(getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case UNDEFINED_BUT_USED: - if (UndefinedButUsed.size() % 2 != 0) - return llvm::createStringError(std::errc::illegal_byte_sequence, - "Invalid existing UndefinedButUsed"); - if (Record.size() % 2 != 0) return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid undefined-but-used record"); for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++])); UndefinedButUsed.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); + {getGlobalDeclID(F, LocalDeclID(Record[I++])), + ReadSourceLocation(F, Record, I).getRawEncoding()}); } break; case DELETE_EXPRS_TO_ANALYZE: for (unsigned I = 0, N = Record.size(); I != N;) { - DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++])); + DelayedDeleteExprs.push_back( + getGlobalDeclID(F, LocalDeclID(Record[I++])).get()); const uint64_t Count = Record[I++]; DelayedDeleteExprs.push_back(Count); for (uint64_t C = 0; C < Count; ++C) { @@ -3976,7 +3976,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES: for (unsigned I = 0, N = Record.size(); I != N; ++I) UnusedLocalTypedefNameCandidates.push_back( - getGlobalDeclID(F, Record[I])); + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH: @@ -4032,7 +4032,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case DECLS_TO_CHECK_FOR_DEFERRED_DIAGS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - DeclsToCheckForDeferredDiags.insert(getGlobalDeclID(F, Record[I])); + DeclsToCheckForDeferredDiags.insert( + getGlobalDeclID(F, LocalDeclID(Record[I]))); break; } } @@ -4655,9 +4656,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type, // that we load any additional categories. if (ContextObj) { for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { - loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), - ObjCClassesLoaded[I], - PreviousGeneration); + loadObjCCategories(GlobalDeclID(ObjCClassesLoaded[I]->getGlobalID()), + ObjCClassesLoaded[I], PreviousGeneration); } } @@ -6010,9 +6010,9 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, case SUBMODULE_INITIALIZERS: { if (!ContextObj) break; - SmallVector Inits; + SmallVector Inits; for (auto &ID : Record) - Inits.push_back(getGlobalDeclID(F, ID)); + Inits.push_back(getGlobalDeclID(F, LocalDeclID(ID)).get()); ContextObj->addLazyModuleInitializers(CurrentModule, Inits); break; } @@ -7517,8 +7517,8 @@ ASTRecordReader::readASTTemplateArgumentListInfo() { return ASTTemplateArgumentListInfo::Create(getContext(), Result); } -Decl *ASTReader::GetExternalDecl(uint32_t ID) { - return GetDecl(ID); +Decl *ASTReader::GetExternalDecl(DeclID ID) { + return GetDecl(GlobalDeclID(ID)); } void ASTReader::CompleteRedeclChain(const Decl *D) { @@ -7652,44 +7652,46 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return Bases; } -serialization::DeclID -ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const { - if (LocalID < NUM_PREDEF_DECL_IDS) - return LocalID; +GlobalDeclID ASTReader::getGlobalDeclID(ModuleFile &F, + LocalDeclID LocalID) const { + DeclID ID = LocalID.get(); + if (ID < NUM_PREDEF_DECL_IDS) + return GlobalDeclID(ID); if (!F.ModuleOffsetMap.empty()) ReadModuleOffsetMap(F); - ContinuousRangeMap::iterator I - = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS); + ContinuousRangeMap::iterator I = + F.DeclRemap.find(ID - NUM_PREDEF_DECL_IDS); assert(I != F.DeclRemap.end() && "Invalid index into decl index remap"); - return LocalID + I->second; + return GlobalDeclID(ID + I->second); } bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const { // Predefined decls aren't from any module. - if (ID < NUM_PREDEF_DECL_IDS) + if (ID.get() < NUM_PREDEF_DECL_IDS) return false; - return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && - ID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls; + return ID.get() - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && + ID.get() - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls; } ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { if (!D->isFromASTFile()) return nullptr; - GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); + GlobalDeclMapType::const_iterator I = + GlobalDeclMap.find(GlobalDeclID(D->getGlobalID())); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); return I->second; } SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) + if (ID.get() < NUM_PREDEF_DECL_IDS) return SourceLocation(); - unsigned Index = ID - NUM_PREDEF_DECL_IDS; + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; if (Index > DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); @@ -7763,10 +7765,10 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { llvm_unreachable("PredefinedDeclIDs unknown enum value"); } -Decl *ASTReader::GetExistingDecl(DeclID ID) { +Decl *ASTReader::GetExistingDecl(GlobalDeclID ID) { assert(ContextObj && "reading decl with no AST context"); - if (ID < NUM_PREDEF_DECL_IDS) { - Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID); + if (ID.get() < NUM_PREDEF_DECL_IDS) { + Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID.get()); if (D) { // Track that we have merged the declaration with ID \p ID into the // pre-existing predefined declaration \p D. @@ -7777,7 +7779,7 @@ Decl *ASTReader::GetExistingDecl(DeclID ID) { return D; } - unsigned Index = ID - NUM_PREDEF_DECL_IDS; + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); @@ -7788,11 +7790,11 @@ Decl *ASTReader::GetExistingDecl(DeclID ID) { return DeclsLoaded[Index]; } -Decl *ASTReader::GetDecl(DeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) +Decl *ASTReader::GetDecl(GlobalDeclID ID) { + if (ID.get() < NUM_PREDEF_DECL_IDS) return GetExistingDecl(ID); - unsigned Index = ID - NUM_PREDEF_DECL_IDS; + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); @@ -7803,16 +7805,17 @@ Decl *ASTReader::GetDecl(DeclID ID) { if (!DeclsLoaded[Index]) { ReadDeclRecord(ID); if (DeserializationListener) - DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); + DeserializationListener->DeclRead(ID.get(), DeclsLoaded[Index]); } return DeclsLoaded[Index]; } DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, - DeclID GlobalID) { - if (GlobalID < NUM_PREDEF_DECL_IDS) - return GlobalID; + GlobalDeclID GlobalID) { + DeclID ID = GlobalID.get(); + if (ID < NUM_PREDEF_DECL_IDS) + return ID; GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); @@ -7823,18 +7826,17 @@ DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, if (Pos == M.GlobalToLocalDeclIDs.end()) return 0; - return GlobalID - Owner->BaseDeclID + Pos->second; + return ID - Owner->BaseDeclID + Pos->second; } -serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, - const RecordData &Record, - unsigned &Idx) { +GlobalDeclID ASTReader::ReadDeclID(ModuleFile &F, const RecordData &Record, + unsigned &Idx) { if (Idx >= Record.size()) { Error("Corrupted AST file"); - return 0; + return GlobalDeclID(0); } - return getGlobalDeclID(F, Record[Idx++]); + return getGlobalDeclID(F, LocalDeclID(Record[Idx++])); } /// Resolve the offset of a statement into a statement. @@ -7881,7 +7883,7 @@ void ASTReader::FindExternalLexicalDecls( PredefsVisited[ID] = true; } - if (Decl *D = GetLocalDecl(*M, ID)) { + if (Decl *D = GetLocalDecl(*M, LocalDeclID(ID))) { assert(D->getKind() == K && "wrong kind for lexical decl"); if (!DC->isDeclInLexicalTraversal(D)) Decls.push_back(D); @@ -7992,7 +7994,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, // Load the list of declarations. SmallVector Decls; llvm::SmallPtrSet Found; - for (DeclID ID : It->second.Table.find(Name)) { + for (GlobalDeclID ID : It->second.Table.find(Name)) { NamedDecl *ND = cast(GetDecl(ID)); if (ND->getDeclName() == Name && Found.insert(ND).second) Decls.push_back(ND); @@ -8013,7 +8015,7 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { DeclsMap Decls; - for (DeclID ID : It->second.Table.findAll()) { + for (GlobalDeclID ID : It->second.Table.findAll()) { NamedDecl *ND = cast(GetDecl(ID)); Decls[ND->getDeclName()].push_back(ND); } @@ -8164,8 +8166,12 @@ dumpModuleIDMap(StringRef Name, llvm::errs() << Name << ":\n"; for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); I != IEnd; ++I) { - llvm::errs() << " " << I->first << " -> " << I->second->FileName - << "\n"; + uint64_t ID = 0; + if constexpr (std::is_integral_v) + ID = I->first; + else /*GlobalDeclID*/ + ID = I->first.get(); + llvm::errs() << " " << ID << " -> " << I->second->FileName << "\n"; } } @@ -8211,7 +8217,7 @@ void ASTReader::InitializeSema(Sema &S) { // Makes sure any declarations that were deserialized "too early" // still get added to the identifier's declaration chains. - for (uint64_t ID : PreloadedDeclIDs) { + for (GlobalDeclID ID : PreloadedDeclIDs) { NamedDecl *D = cast(GetDecl(ID)); pushExternalDeclIntoScope(D, D->getDeclName()); } @@ -8240,11 +8246,11 @@ void ASTReader::UpdateSema() { assert(SemaDeclRefs.size() % 3 == 0); for (unsigned I = 0; I != SemaDeclRefs.size(); I += 3) { if (!SemaObj->StdNamespace) - SemaObj->StdNamespace = SemaDeclRefs[I]; + SemaObj->StdNamespace = SemaDeclRefs[I].get(); if (!SemaObj->StdBadAlloc) - SemaObj->StdBadAlloc = SemaDeclRefs[I+1]; + SemaObj->StdBadAlloc = SemaDeclRefs[I + 1].get(); if (!SemaObj->StdAlignValT) - SemaObj->StdAlignValT = SemaDeclRefs[I+2]; + SemaObj->StdAlignValT = SemaDeclRefs[I + 2].get(); } SemaDeclRefs.clear(); } @@ -8617,18 +8623,20 @@ void ASTReader::ReadKnownNamespaces( void ASTReader::ReadUndefinedButUsed( llvm::MapVector &Undefined) { for (unsigned Idx = 0, N = UndefinedButUsed.size(); Idx != N;) { - NamedDecl *D = cast(GetDecl(UndefinedButUsed[Idx++])); - SourceLocation Loc = - SourceLocation::getFromRawEncoding(UndefinedButUsed[Idx++]); + UndefinedButUsedDecl &U = UndefinedButUsed[Idx++]; + NamedDecl *D = cast(GetDecl(U.ID)); + SourceLocation Loc = SourceLocation::getFromRawEncoding(U.RawLoc); Undefined.insert(std::make_pair(D, Loc)); } + UndefinedButUsed.clear(); } void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector< FieldDecl *, llvm::SmallVector, 4>> & Exprs) { for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) { - FieldDecl *FD = cast(GetDecl(DelayedDeleteExprs[Idx++])); + FieldDecl *FD = + cast(GetDecl(GlobalDeclID(DelayedDeleteExprs[Idx++]))); uint64_t Count = DelayedDeleteExprs[Idx++]; for (uint64_t C = 0; C < Count; ++C) { SourceLocation DeleteLoc = @@ -8742,9 +8750,10 @@ void ASTReader::ReadWeakUndeclaredIdentifiers( void ASTReader::ReadUsedVTables(SmallVectorImpl &VTables) { for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) { ExternalVTableUse VT; - VT.Record = dyn_cast_or_null(GetDecl(VTableUses[Idx++])); - VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]); - VT.DefinitionRequired = VTableUses[Idx++]; + VTableUse &TableInfo = VTableUses[Idx++]; + VT.Record = dyn_cast_or_null(GetDecl(TableInfo.ID)); + VT.Location = SourceLocation::getFromRawEncoding(TableInfo.RawLoc); + VT.DefinitionRequired = TableInfo.Used; VTables.push_back(VT); } @@ -8754,9 +8763,9 @@ void ASTReader::ReadUsedVTables(SmallVectorImpl &VTables) { void ASTReader::ReadPendingInstantiations( SmallVectorImpl> &Pending) { for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) { - ValueDecl *D = cast(GetDecl(PendingInstantiations[Idx++])); - SourceLocation Loc - = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]); + PendingInstantiation &Inst = PendingInstantiations[Idx++]; + ValueDecl *D = cast(GetDecl(Inst.ID)); + SourceLocation Loc = SourceLocation::getFromRawEncoding(Inst.RawLoc); Pending.push_back(std::make_pair(D, Loc)); } @@ -8771,11 +8780,11 @@ void ASTReader::ReadLateParsedTemplates( RecordDataImpl &LateParsed = LPT.second; for (unsigned Idx = 0, N = LateParsed.size(); Idx < N; /* In loop */) { - FunctionDecl *FD = - cast(GetLocalDecl(*FMod, LateParsed[Idx++])); + FunctionDecl *FD = cast( + GetLocalDecl(*FMod, LocalDeclID(LateParsed[Idx++]))); auto LT = std::make_unique(); - LT->D = GetLocalDecl(*FMod, LateParsed[Idx++]); + LT->D = GetLocalDecl(*FMod, LocalDeclID(LateParsed[Idx++])); LT->FPO = FPOptions::getFromOpaqueInt(LateParsed[Idx++]); ModuleFile *F = getOwningModuleFile(LT->D); @@ -8833,10 +8842,9 @@ void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) { /// \param Decls if non-null, this vector will be populated with the set of /// deserialized declarations. These declarations will not be pushed into /// scope. -void -ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, - const SmallVectorImpl &DeclIDs, - SmallVectorImpl *Decls) { +void ASTReader::SetGloballyVisibleDecls( + IdentifierInfo *II, const SmallVectorImpl &DeclIDs, + SmallVectorImpl *Decls) { if (NumCurrentElementsDeserializing && !Decls) { PendingIdentifierInfos[II].append(DeclIDs.begin(), DeclIDs.end()); return; @@ -9184,9 +9192,9 @@ void ASTRecordReader::readUnresolvedSet(LazyASTUnresolvedSet &Set) { unsigned NumDecls = readInt(); Set.reserve(getContext(), NumDecls); while (NumDecls--) { - DeclID ID = readDeclID(); + GlobalDeclID ID = readDeclID(); AccessSpecifier AS = (AccessSpecifier) readInt(); - Set.addLazyDecl(getContext(), ID, AS); + Set.addLazyDecl(getContext(), ID.get(), AS); } } @@ -9560,7 +9568,7 @@ void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty()) { IdentifierInfo *II = PendingIdentifierInfos.back().first; - SmallVector DeclIDs = + SmallVector DeclIDs = std::move(PendingIdentifierInfos.back().second); PendingIdentifierInfos.pop_back(); @@ -11786,6 +11794,15 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc, CondExpr, EndLoc); } + case OpenACCClauseKind::NumGangs: { + SourceLocation LParenLoc = readSourceLocation(); + unsigned NumClauses = readInt(); + llvm::SmallVector IntExprs; + for (unsigned I = 0; I < NumClauses; ++I) + IntExprs.push_back(readSubExpr()); + return OpenACCNumGangsClause::Create(getContext(), BeginLoc, LParenLoc, + IntExprs, EndLoc); + } case OpenACCClauseKind::NumWorkers: { SourceLocation LParenLoc = readSourceLocation(); Expr *IntExpr = readSubExpr(); @@ -11826,7 +11843,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::DeviceType: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 74d40f7da34cadec03934f890f311e4c8cca9de8..bb82173dfe0b3ac6a0320d2b8aef8f1848b52307 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -84,14 +84,14 @@ namespace clang { ASTReader &Reader; ASTRecordReader &Record; ASTReader::RecordLocation Loc; - const DeclID ThisDeclID; + const GlobalDeclID ThisDeclID; const SourceLocation ThisDeclLoc; using RecordData = ASTReader::RecordData; TypeID DeferredTypeID = 0; unsigned AnonymousDeclNumber = 0; - GlobalDeclID NamedDeclForTagDecl = 0; + GlobalDeclID NamedDeclForTagDecl = GlobalDeclID(); IdentifierInfo *TypedefNameForLinkage = nullptr; ///A flag to carry the information for a decl from the entity is @@ -124,15 +124,13 @@ namespace clang { return Record.readTypeSourceInfo(); } - serialization::DeclID readDeclID() { - return Record.readDeclID(); - } + GlobalDeclID readDeclID() { return Record.readDeclID(); } std::string readString() { return Record.readString(); } - void readDeclIDList(SmallVectorImpl &IDs) { + void readDeclIDList(SmallVectorImpl &IDs) { for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I) IDs.push_back(readDeclID()); } @@ -258,14 +256,14 @@ namespace clang { public: ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record, - ASTReader::RecordLocation Loc, - DeclID thisDeclID, SourceLocation ThisDeclLoc) + ASTReader::RecordLocation Loc, GlobalDeclID thisDeclID, + SourceLocation ThisDeclLoc) : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID), ThisDeclLoc(ThisDeclLoc) {} - template static - void AddLazySpecializations(T *D, - SmallVectorImpl& IDs) { + template + static void AddLazySpecializations(T *D, + SmallVectorImpl &IDs) { if (IDs.empty()) return; @@ -275,14 +273,17 @@ namespace clang { auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; if (auto &Old = LazySpecializations) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + IDs.insert(IDs.end(), GlobalDeclIDIterator(Old + 1), + GlobalDeclIDIterator(Old + 1 + Old[0])); llvm::sort(IDs); IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); } auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; *Result = IDs.size(); - std::copy(IDs.begin(), IDs.end(), Result + 1); + + std::copy(DeclIDIterator(IDs.begin()), DeclIDIterator(IDs.end()), + Result + 1); LazySpecializations = Result; } @@ -315,7 +316,7 @@ namespace clang { void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D, SmallVectorImpl &); + void UpdateDecl(Decl *D, SmallVectorImpl &); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -557,7 +558,7 @@ void ASTDeclReader::Visit(Decl *D) { // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. - if (NamedDeclForTagDecl) + if (NamedDeclForTagDecl != GlobalDeclID()) cast(D)->TypedefNameDeclOrQualifier = cast(Reader.GetDecl(NamedDeclForTagDecl)); } else if (auto *ID = dyn_cast(D)) { @@ -601,8 +602,8 @@ void ASTDeclReader::VisitDecl(Decl *D) { // placeholder. GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID(); GlobalDeclID LexicalDCIDForTemplateParmDecl = - HasStandaloneLexicalDC ? readDeclID() : 0; - if (!LexicalDCIDForTemplateParmDecl) + HasStandaloneLexicalDC ? readDeclID() : GlobalDeclID(); + if (LexicalDCIDForTemplateParmDecl == GlobalDeclID()) LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl; Reader.addPendingDeclContextInfo(D, SemaDCIDForTemplateParmDecl, @@ -1848,7 +1849,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // this namespace; loading it might load a later declaration of the // same namespace, and we have an invariant that older declarations // get merged before newer ones try to merge. - GlobalDeclID AnonNamespace = 0; + GlobalDeclID AnonNamespace; if (Redecl.getFirstID() == ThisDeclID) { AnonNamespace = readDeclID(); } else { @@ -1859,7 +1860,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { mergeRedeclarable(D, Redecl); - if (AnonNamespace) { + if (AnonNamespace != GlobalDeclID()) { // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. @@ -2019,7 +2020,7 @@ void ASTDeclReader::ReadCXXDefinitionData( if (Data.NumVBases) Data.VBases = ReadGlobalOffset(); - Data.FirstFriend = readDeclID(); + Data.FirstFriend = readDeclID().get(); } else { using Capture = LambdaCapture; @@ -2278,12 +2279,12 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // Lazily load the key function to avoid deserializing every method so we can // compute it. if (WasDefinition) { - DeclID KeyFn = readDeclID(); - if (KeyFn && D->isCompleteDefinition()) + GlobalDeclID KeyFn = readDeclID(); + if (KeyFn.get() && D->isCompleteDefinition()) // FIXME: This is wrong for the ARM ABI, where some other module may have // made this function no longer be a key function. We need an update // record or similar for that case. - C.KeyFunctions[D] = KeyFn; + C.KeyFunctions[D] = KeyFn.get(); } return Redecl; @@ -2372,7 +2373,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { for (unsigned i = 0; i != D->NumTPLists; ++i) D->getTrailingObjects()[i] = Record.readTemplateParameterList(); - D->NextFriend = readDeclID(); + D->NextFriend = readDeclID().get(); D->UnsupportedFriend = (Record.readInt() != 0); D->FriendLoc = readSourceLocation(); } @@ -2457,7 +2458,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector SpecIDs; + SmallVector SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2485,7 +2486,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector SpecIDs; + SmallVector SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2587,7 +2588,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. - SmallVector SpecIDs; + SmallVector SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2783,7 +2784,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { template ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRedeclarable(Redeclarable *D) { - DeclID FirstDeclID = readDeclID(); + GlobalDeclID FirstDeclID = readDeclID(); Decl *MergeWith = nullptr; bool IsKeyDecl = ThisDeclID == FirstDeclID; @@ -2793,7 +2794,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable *D) { // 0 indicates that this declaration was the only declaration of its entity, // and is used for space optimization. - if (FirstDeclID == 0) { + if (FirstDeclID == GlobalDeclID()) { FirstDeclID = ThisDeclID; IsKeyDecl = true; IsFirstLocalDecl = true; @@ -2922,9 +2923,9 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, bool IsKeyDecl) { auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); - RedeclarableResult Result(/*MergeWith*/ ExistingPattern, - DPattern->getCanonicalDecl()->getGlobalID(), - IsKeyDecl); + RedeclarableResult Result( + /*MergeWith*/ ExistingPattern, + GlobalDeclID(DPattern->getCanonicalDecl()->getGlobalID()), IsKeyDecl); if (auto *DClass = dyn_cast(DPattern)) { // Merge with any existing definition. @@ -3079,14 +3080,14 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Expr *Init = Record.readExpr(); auto IK = static_cast(Record.readInt()); D->setInitializer(Init, IK); - D->PrevDeclInScope = readDeclID(); + D->PrevDeclInScope = readDeclID().get(); } void ASTDeclReader::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { Record.readOMPChildren(D->Data); VisitValueDecl(D); D->VarName = Record.readDeclarationName(); - D->PrevDeclInScope = readDeclID(); + D->PrevDeclInScope = readDeclID().get(); } void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { @@ -3140,7 +3141,7 @@ public: OMPTraitInfo *readOMPTraitInfo() { return Reader.readOMPTraitInfo(); } - template T *GetLocalDeclAs(uint32_t LocalID) { + template T *GetLocalDeclAs(LocalDeclID LocalID) { return Reader.GetLocalDeclAs(LocalID); } }; @@ -3243,13 +3244,13 @@ bool ASTReader::isConsumerInterestedIn(Decl *D) { } /// Get the correct cursor and offset for loading a declaration. -ASTReader::RecordLocation -ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) { +ASTReader::RecordLocation ASTReader::DeclCursorForID(GlobalDeclID ID, + SourceLocation &Loc) { GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); ModuleFile *M = I->second; const DeclOffset &DOffs = - M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; + M->DeclOffsets[ID.get() - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; Loc = TranslateSourceLocation(*M, DOffs.getLocation()); return RecordLocation(M, DOffs.getBitOffset(M->DeclsBlockStartOffset)); } @@ -3792,8 +3793,8 @@ void ASTReader::markIncompleteDeclChain(Decl *D) { } /// Read the declaration at the given offset from the AST file. -Decl *ASTReader::ReadDeclRecord(DeclID ID) { - unsigned Index = ID - NUM_PREDEF_DECL_IDS; +Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { + unsigned Index = ID.get() - NUM_PREDEF_DECL_IDS; SourceLocation DeclLoc; RecordLocation Loc = DeclCursorForID(ID, DeclLoc); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; @@ -3827,233 +3828,241 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { llvm::report_fatal_error( Twine("ASTReader::readDeclRecord failed reading decl code: ") + toString(MaybeDeclCode.takeError())); + + DeclID RawGlobalID = ID.get(); switch ((DeclCode)MaybeDeclCode.get()) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: llvm_unreachable("Record cannot be de-serialized with readDeclRecord"); case DECL_TYPEDEF: - D = TypedefDecl::CreateDeserialized(Context, ID); + D = TypedefDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_TYPEALIAS: - D = TypeAliasDecl::CreateDeserialized(Context, ID); + D = TypeAliasDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_ENUM: - D = EnumDecl::CreateDeserialized(Context, ID); + D = EnumDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_RECORD: - D = RecordDecl::CreateDeserialized(Context, ID); + D = RecordDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_ENUM_CONSTANT: - D = EnumConstantDecl::CreateDeserialized(Context, ID); + D = EnumConstantDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_FUNCTION: - D = FunctionDecl::CreateDeserialized(Context, ID); + D = FunctionDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::CreateDeserialized(Context, ID); + D = LinkageSpecDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_EXPORT: - D = ExportDecl::CreateDeserialized(Context, ID); + D = ExportDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_LABEL: - D = LabelDecl::CreateDeserialized(Context, ID); + D = LabelDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_NAMESPACE: - D = NamespaceDecl::CreateDeserialized(Context, ID); + D = NamespaceDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_NAMESPACE_ALIAS: - D = NamespaceAliasDecl::CreateDeserialized(Context, ID); + D = NamespaceAliasDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_USING: - D = UsingDecl::CreateDeserialized(Context, ID); + D = UsingDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_USING_PACK: - D = UsingPackDecl::CreateDeserialized(Context, ID, Record.readInt()); + D = UsingPackDecl::CreateDeserialized(Context, RawGlobalID, + Record.readInt()); break; case DECL_USING_SHADOW: - D = UsingShadowDecl::CreateDeserialized(Context, ID); + D = UsingShadowDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_USING_ENUM: - D = UsingEnumDecl::CreateDeserialized(Context, ID); + D = UsingEnumDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CONSTRUCTOR_USING_SHADOW: - D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID); + D = ConstructorUsingShadowDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_USING_DIRECTIVE: - D = UsingDirectiveDecl::CreateDeserialized(Context, ID); + D = UsingDirectiveDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_UNRESOLVED_USING_VALUE: - D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID); + D = UnresolvedUsingValueDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_UNRESOLVED_USING_TYPENAME: - D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID); + D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_UNRESOLVED_USING_IF_EXISTS: - D = UnresolvedUsingIfExistsDecl::CreateDeserialized(Context, ID); + D = UnresolvedUsingIfExistsDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CXX_RECORD: - D = CXXRecordDecl::CreateDeserialized(Context, ID); + D = CXXRecordDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CXX_DEDUCTION_GUIDE: - D = CXXDeductionGuideDecl::CreateDeserialized(Context, ID); + D = CXXDeductionGuideDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CXX_METHOD: - D = CXXMethodDecl::CreateDeserialized(Context, ID); + D = CXXMethodDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CXX_CONSTRUCTOR: - D = CXXConstructorDecl::CreateDeserialized(Context, ID, Record.readInt()); + D = CXXConstructorDecl::CreateDeserialized(Context, RawGlobalID, + Record.readInt()); break; case DECL_CXX_DESTRUCTOR: - D = CXXDestructorDecl::CreateDeserialized(Context, ID); + D = CXXDestructorDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CXX_CONVERSION: - D = CXXConversionDecl::CreateDeserialized(Context, ID); + D = CXXConversionDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_ACCESS_SPEC: - D = AccessSpecDecl::CreateDeserialized(Context, ID); + D = AccessSpecDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_FRIEND: - D = FriendDecl::CreateDeserialized(Context, ID, Record.readInt()); + D = FriendDecl::CreateDeserialized(Context, RawGlobalID, Record.readInt()); break; case DECL_FRIEND_TEMPLATE: - D = FriendTemplateDecl::CreateDeserialized(Context, ID); + D = FriendTemplateDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::CreateDeserialized(Context, ID); + D = ClassTemplateDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CLASS_TEMPLATE_SPECIALIZATION: - D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID); + D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, + RawGlobalID); break; case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: - D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); + D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, + RawGlobalID); break; case DECL_VAR_TEMPLATE: - D = VarTemplateDecl::CreateDeserialized(Context, ID); + D = VarTemplateDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_VAR_TEMPLATE_SPECIALIZATION: - D = VarTemplateSpecializationDecl::CreateDeserialized(Context, ID); + D = VarTemplateSpecializationDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION: - D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); + D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, + RawGlobalID); break; case DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::CreateDeserialized(Context, ID); + D = FunctionTemplateDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_TEMPLATE_TYPE_PARM: { bool HasTypeConstraint = Record.readInt(); - D = TemplateTypeParmDecl::CreateDeserialized(Context, ID, + D = TemplateTypeParmDecl::CreateDeserialized(Context, RawGlobalID, HasTypeConstraint); break; } case DECL_NON_TYPE_TEMPLATE_PARM: { bool HasTypeConstraint = Record.readInt(); - D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, + D = NonTypeTemplateParmDecl::CreateDeserialized(Context, RawGlobalID, HasTypeConstraint); break; } case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: { bool HasTypeConstraint = Record.readInt(); - D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, - Record.readInt(), - HasTypeConstraint); + D = NonTypeTemplateParmDecl::CreateDeserialized( + Context, RawGlobalID, Record.readInt(), HasTypeConstraint); break; } case DECL_TEMPLATE_TEMPLATE_PARM: - D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID); + D = TemplateTemplateParmDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK: - D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID, + D = TemplateTemplateParmDecl::CreateDeserialized(Context, RawGlobalID, Record.readInt()); break; case DECL_TYPE_ALIAS_TEMPLATE: - D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID); + D = TypeAliasTemplateDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CONCEPT: - D = ConceptDecl::CreateDeserialized(Context, ID); + D = ConceptDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_REQUIRES_EXPR_BODY: - D = RequiresExprBodyDecl::CreateDeserialized(Context, ID); + D = RequiresExprBodyDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_STATIC_ASSERT: - D = StaticAssertDecl::CreateDeserialized(Context, ID); + D = StaticAssertDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_METHOD: - D = ObjCMethodDecl::CreateDeserialized(Context, ID); + D = ObjCMethodDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::CreateDeserialized(Context, ID); + D = ObjCInterfaceDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_IVAR: - D = ObjCIvarDecl::CreateDeserialized(Context, ID); + D = ObjCIvarDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_PROTOCOL: - D = ObjCProtocolDecl::CreateDeserialized(Context, ID); + D = ObjCProtocolDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID); + D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_CATEGORY: - D = ObjCCategoryDecl::CreateDeserialized(Context, ID); + D = ObjCCategoryDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_CATEGORY_IMPL: - D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID); + D = ObjCCategoryImplDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_IMPLEMENTATION: - D = ObjCImplementationDecl::CreateDeserialized(Context, ID); + D = ObjCImplementationDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_COMPATIBLE_ALIAS: - D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID); + D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_PROPERTY: - D = ObjCPropertyDecl::CreateDeserialized(Context, ID); + D = ObjCPropertyDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_PROPERTY_IMPL: - D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID); + D = ObjCPropertyImplDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_FIELD: - D = FieldDecl::CreateDeserialized(Context, ID); + D = FieldDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_INDIRECTFIELD: - D = IndirectFieldDecl::CreateDeserialized(Context, ID); + D = IndirectFieldDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_VAR: - D = VarDecl::CreateDeserialized(Context, ID); + D = VarDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_IMPLICIT_PARAM: - D = ImplicitParamDecl::CreateDeserialized(Context, ID); + D = ImplicitParamDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_PARM_VAR: - D = ParmVarDecl::CreateDeserialized(Context, ID); + D = ParmVarDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_DECOMPOSITION: - D = DecompositionDecl::CreateDeserialized(Context, ID, Record.readInt()); + D = DecompositionDecl::CreateDeserialized(Context, RawGlobalID, + Record.readInt()); break; case DECL_BINDING: - D = BindingDecl::CreateDeserialized(Context, ID); + D = BindingDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::CreateDeserialized(Context, ID); + D = FileScopeAsmDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_TOP_LEVEL_STMT_DECL: - D = TopLevelStmtDecl::CreateDeserialized(Context, ID); + D = TopLevelStmtDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_BLOCK: - D = BlockDecl::CreateDeserialized(Context, ID); + D = BlockDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_MS_PROPERTY: - D = MSPropertyDecl::CreateDeserialized(Context, ID); + D = MSPropertyDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_MS_GUID: - D = MSGuidDecl::CreateDeserialized(Context, ID); + D = MSGuidDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_UNNAMED_GLOBAL_CONSTANT: - D = UnnamedGlobalConstantDecl::CreateDeserialized(Context, ID); + D = UnnamedGlobalConstantDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_TEMPLATE_PARAM_OBJECT: - D = TemplateParamObjectDecl::CreateDeserialized(Context, ID); + D = TemplateParamObjectDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_CAPTURED: - D = CapturedDecl::CreateDeserialized(Context, ID, Record.readInt()); + D = CapturedDecl::CreateDeserialized(Context, RawGlobalID, + Record.readInt()); break; case DECL_CXX_BASE_SPECIFIERS: Error("attempt to read a C++ base-specifier record as a declaration"); @@ -4064,62 +4073,66 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_IMPORT: // Note: last entry of the ImportDecl record is the number of stored source // locations. - D = ImportDecl::CreateDeserialized(Context, ID, Record.back()); + D = ImportDecl::CreateDeserialized(Context, RawGlobalID, Record.back()); break; case DECL_OMP_THREADPRIVATE: { Record.skipInts(1); unsigned NumChildren = Record.readInt(); Record.skipInts(1); - D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, NumChildren); + D = OMPThreadPrivateDecl::CreateDeserialized(Context, RawGlobalID, + NumChildren); break; } case DECL_OMP_ALLOCATE: { unsigned NumClauses = Record.readInt(); unsigned NumVars = Record.readInt(); Record.skipInts(1); - D = OMPAllocateDecl::CreateDeserialized(Context, ID, NumVars, NumClauses); + D = OMPAllocateDecl::CreateDeserialized(Context, RawGlobalID, NumVars, + NumClauses); break; } case DECL_OMP_REQUIRES: { unsigned NumClauses = Record.readInt(); Record.skipInts(2); - D = OMPRequiresDecl::CreateDeserialized(Context, ID, NumClauses); + D = OMPRequiresDecl::CreateDeserialized(Context, RawGlobalID, NumClauses); break; } case DECL_OMP_DECLARE_REDUCTION: - D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID); + D = OMPDeclareReductionDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OMP_DECLARE_MAPPER: { unsigned NumClauses = Record.readInt(); Record.skipInts(2); - D = OMPDeclareMapperDecl::CreateDeserialized(Context, ID, NumClauses); + D = OMPDeclareMapperDecl::CreateDeserialized(Context, RawGlobalID, + NumClauses); break; } case DECL_OMP_CAPTUREDEXPR: - D = OMPCapturedExprDecl::CreateDeserialized(Context, ID); + D = OMPCapturedExprDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_PRAGMA_COMMENT: - D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record.readInt()); + D = PragmaCommentDecl::CreateDeserialized(Context, RawGlobalID, + Record.readInt()); break; case DECL_PRAGMA_DETECT_MISMATCH: - D = PragmaDetectMismatchDecl::CreateDeserialized(Context, ID, + D = PragmaDetectMismatchDecl::CreateDeserialized(Context, RawGlobalID, Record.readInt()); break; case DECL_EMPTY: - D = EmptyDecl::CreateDeserialized(Context, ID); + D = EmptyDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_LIFETIME_EXTENDED_TEMPORARY: - D = LifetimeExtendedTemporaryDecl::CreateDeserialized(Context, ID); + D = LifetimeExtendedTemporaryDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_OBJC_TYPE_PARAM: - D = ObjCTypeParamDecl::CreateDeserialized(Context, ID); + D = ObjCTypeParamDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_HLSL_BUFFER: - D = HLSLBufferDecl::CreateDeserialized(Context, ID); + D = HLSLBufferDecl::CreateDeserialized(Context, RawGlobalID); break; case DECL_IMPLICIT_CONCEPT_SPECIALIZATION: - D = ImplicitConceptSpecializationDecl::CreateDeserialized(Context, ID, - Record.readInt()); + D = ImplicitConceptSpecializationDecl::CreateDeserialized( + Context, RawGlobalID, Record.readInt()); break; } @@ -4207,7 +4220,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); - SmallVector PendingLazySpecializationIDs; + SmallVector PendingLazySpecializationIDs; if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); @@ -4327,7 +4340,7 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { // we should instead generate one loop per kind and dispatch up-front? Decl *MostRecent = FirstLocal; for (unsigned I = 0, N = Record.size(); I != N; ++I) { - auto *D = GetLocalDecl(*M, Record[N - I - 1]); + auto *D = GetLocalDecl(*M, LocalDeclID(Record[N - I - 1])); ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl); MostRecent = D; } @@ -4437,7 +4450,7 @@ namespace { M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again for (unsigned I = 0; I != N; ++I) add(cast_or_null( - Reader.GetLocalDecl(M, M.ObjCCategories[Offset++]))); + Reader.GetLocalDecl(M, LocalDeclID(M.ObjCCategories[Offset++])))); return true; } }; @@ -4473,8 +4486,9 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D, - llvm::SmallVectorImpl &PendingLazySpecializationIDs) { +void ASTDeclReader::UpdateDecl( + Decl *D, + llvm::SmallVectorImpl &PendingLazySpecializationIDs) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { diff --git a/clang/lib/Serialization/ASTReaderInternals.h b/clang/lib/Serialization/ASTReaderInternals.h index 25a46ddabcb7078cd234092076f6bdfbc1807302..49268ad5251dff2a852a834c317339cd972ecaf4 100644 --- a/clang/lib/Serialization/ASTReaderInternals.h +++ b/clang/lib/Serialization/ASTReaderInternals.h @@ -49,15 +49,15 @@ public: static const int MaxTables = 4; /// The lookup result is a list of global declaration IDs. - using data_type = SmallVector; + using data_type = SmallVector; struct data_type_builder { data_type &Data; - llvm::DenseSet Found; + llvm::DenseSet Found; data_type_builder(data_type &D) : Data(D) {} - void insert(DeclID ID) { + void insert(GlobalDeclID ID) { // Just use a linear scan unless we have more than a few IDs. if (Found.empty() && !Data.empty()) { if (Data.size() <= 4) { @@ -108,7 +108,7 @@ public: static void MergeDataInto(const data_type &From, data_type_builder &To) { To.Data.reserve(To.Data.size() + From.size()); - for (DeclID ID : From) + for (GlobalDeclID ID : From) To.insert(ID); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index ca0460800898b3292e2b70758b96eb3d803b5659..baded0fe19831ff62d6b8d5739093fcad8407b20 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2096,7 +2096,6 @@ void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); E->UnresolvedLookupExprBits.RequiresADL = CurrentUnpackingBits->getNextBit(); - E->UnresolvedLookupExprBits.Overloaded = CurrentUnpackingBits->getNextBit(); E->NamingClass = readDeclAs(); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6dd87b5d200db6141dfb58ec7e56b8ff95c0bda1..21cf72ab0f912146fc89b1be2b91a2c7f5f4418b 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -166,9 +166,9 @@ namespace { std::optional> GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { - // Without implicit module map search, there's no good reason to know about - // any module maps that are not affecting. - if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ImplicitModuleMaps) + if (!PP.getHeaderSearchInfo() + .getHeaderSearchOpts() + .ModulesPruneNonAffectingModuleMaps) return std::nullopt; SmallVector ModulesToProcess{RootModule}; @@ -3210,7 +3210,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, return 0; uint64_t Offset = Stream.GetCurrentBitNo(); - SmallVector KindDeclPairs; + SmallVector KindDeclPairs; for (const auto *D : DC->decls()) { if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D)) continue; @@ -3348,11 +3348,11 @@ public: for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - DataLen += 4; + DataLen += sizeof(DeclID); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - DataLen += 4; + DataLen += sizeof(DeclID); return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3410,11 +3410,11 @@ public: for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - LE.write(Writer.getDeclID(Method->getMethod())); + LE.write(Writer.getDeclID(Method->getMethod())); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - LE.write(Writer.getDeclID(Method->getMethod())); + LE.write(Writer.getDeclID(Method->getMethod())); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -3687,7 +3687,8 @@ public: DataLen += 4; // MacroDirectives offset. if (NeedDecls) - DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * 4; + DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * + sizeof(DeclID); } return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3733,7 +3734,7 @@ public: // Only emit declarations that aren't from a chained PCH, though. SmallVector Decls(IdResolver.decls(II)); for (NamedDecl *D : llvm::reverse(Decls)) - LE.write( + LE.write( Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), D))); } } @@ -3883,7 +3884,8 @@ public: data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { unsigned Start = DeclIDs.size(); - llvm::append_range(DeclIDs, FromReader); + DeclIDs.insert(DeclIDs.end(), DeclIDIterator(FromReader.begin()), + DeclIDIterator(FromReader.end())); return std::make_pair(Start, DeclIDs.size()); } @@ -3928,8 +3930,8 @@ public: break; } - // 4 bytes for each DeclID. - unsigned DataLen = 4 * (Lookup.second - Lookup.first); + // length of DeclIDs. + unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first); return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3972,7 +3974,7 @@ public: endian::Writer LE(Out, llvm::endianness::little); uint64_t Start = Out.tell(); (void)Start; for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) - LE.write(DeclIDs[I]); + LE.write(DeclIDs[I]); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; @@ -5095,7 +5097,7 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) { DeclsToCheckForDeferredDiags.push_back(getDeclID(D)); if (!DeclsToCheckForDeferredDiags.empty()) Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, - DeclsToCheckForDeferredDiags); + DeclsToCheckForDeferredDiags); // Write the record containing CUDA-specific declaration references. RecordData CUDASpecialDeclRefs; @@ -5486,7 +5488,7 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. - SmallVector NewGlobalKindDeclPairs; + SmallVector NewGlobalKindDeclPairs; for (const auto *D : TU->noload_decls()) { if (D->isFromASTFile()) continue; @@ -7657,6 +7659,14 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { AddStmt(const_cast(SC->getConditionExpr())); return; } + case OpenACCClauseKind::NumGangs: { + const auto *NGC = cast(C); + writeSourceLocation(NGC->getLParenLoc()); + writeUInt32(NGC->getIntExprs().size()); + for (Expr *E : NGC->getIntExprs()) + AddStmt(E); + return; + } case OpenACCClauseKind::NumWorkers: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); @@ -7697,7 +7707,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::DeviceType: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index a736a7b0ef726ca5a40745d058b8dbda492beb5d..cd5f733baf76f4e5d6cfb3004d2fd375fa2281b6 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2082,7 +2082,6 @@ void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); CurrentPackingBits.addBit(E->requiresADL()); - CurrentPackingBits.addBit(E->isOverloaded()); Record.AddDeclRef(E->getNamingClass()); Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; } diff --git a/clang/lib/StaticAnalyzer/Checkers/Taint.cpp b/clang/lib/StaticAnalyzer/Checkers/Taint.cpp index 4edb671753bf453bc466333d60e53f02f48e83b9..6362c82b009d7284c9e72638ac6ca0b97d02597e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Taint.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/Taint.cpp @@ -216,21 +216,17 @@ std::vector taint::getTaintedSymbolsImpl(ProgramStateRef State, std::vector TaintedSymbols; if (!Reg) return TaintedSymbols; - // Element region (array element) is tainted if either the base or the offset - // are tainted. + + // Element region (array element) is tainted if the offset is tainted. if (const ElementRegion *ER = dyn_cast(Reg)) { std::vector TaintedIndex = getTaintedSymbolsImpl(State, ER->getIndex(), K, returnFirstOnly); llvm::append_range(TaintedSymbols, TaintedIndex); if (returnFirstOnly && !TaintedSymbols.empty()) return TaintedSymbols; // return early if needed - std::vector TaintedSuperRegion = - getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly); - llvm::append_range(TaintedSymbols, TaintedSuperRegion); - if (returnFirstOnly && !TaintedSymbols.empty()) - return TaintedSymbols; // return early if needed } + // Symbolic region is tainted if the corresponding symbol is tainted. if (const SymbolicRegion *SR = dyn_cast(Reg)) { std::vector TaintedRegions = getTaintedSymbolsImpl(State, SR->getSymbol(), K, returnFirstOnly); @@ -239,6 +235,8 @@ std::vector taint::getTaintedSymbolsImpl(ProgramStateRef State, return TaintedSymbols; // return early if needed } + // Any subregion (including Element and Symbolic regions) is tainted if its + // super-region is tainted. if (const SubRegion *ER = dyn_cast(Reg)) { std::vector TaintedSubRegions = getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly); @@ -318,4 +316,4 @@ std::vector taint::getTaintedSymbolsImpl(ProgramStateRef State, } } return TaintedSymbols; -} \ No newline at end of file +} diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index ebba181eb2d842b4f05baa56d196c7d8997e02c0..ba29c12313901686c5939a20dbeadc8610971fad 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2358,11 +2358,12 @@ StoreRef RegionStoreManager::killBinding(Store ST, Loc L) { RegionBindingsRef RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) { - if (L.getAs()) + // We only care about region locations. + auto MemRegVal = L.getAs(); + if (!MemRegVal) return B; - // If we get here, the location should be a region. - const MemRegion *R = L.castAs().getRegion(); + const MemRegion *R = MemRegVal->getRegion(); // Check if the region is a struct region. if (const TypedValueRegion* TR = dyn_cast(R)) { diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index e19f19b2528c1540912bc3fe359a0193fe66c977..f46324ee9989eb87ad06a28a344f9c0cf8431b22 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -179,6 +179,11 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) { CI.resetNonModularOptions(); CI.clearImplicitModuleBuildOptions(); + // The scanner takes care to avoid passing non-affecting module maps to the + // explicit compiles. No need to do extra work just to find out there are no + // module map files to prune. + CI.getHeaderSearchOpts().ModulesPruneNonAffectingModuleMaps = false; + // Remove options incompatible with explicit module build or are likely to // differ between identical modules discovered from different translation // units. diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 1a29a664d7ce5497495b4948484b4707b63e4fed..0cbab1fcd91d091ce85d7ce0afaaecca85cfa148 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -633,3 +633,9 @@ void test7(void) { X = CFSTR("foo", "bar"); // both-error {{too many arguments to function call}} #endif } + +/// The actual value on my machine is 22, but I have a feeling this will be different +/// on other targets, so just checking for != 0 here. Light testing is fine since +/// the actual implementation uses analyze_os_log::computeOSLogBufferLayout(), which +/// is tested elsewhere. +static_assert(__builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc") != 0, ""); diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 5ae9b1dc7bff869ba6586737d847bc75d3c2ea67..a5951158ed0e0d808303711ae1e69475fd006015 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -257,3 +257,9 @@ int Y __attribute__((annotate( 42, (struct TestStruct) { .a = 1, .b = 2 } ))); + +#ifdef __SIZEOF_INT128__ +const int *p = &b; +const __int128 K = (__int128)(int*)0; +const unsigned __int128 KU = (unsigned __int128)(int*)0; +#endif diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 277438d2e6311431e60bb3c81a08261cf568e17a..2688b53adde2483bb801715f151f23ee44578926 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -1209,4 +1209,16 @@ constexpr int externvar1() { // both-error {{never produces a constant expressio namespace Extern { constexpr extern char Oops = 1; static_assert(Oops == 1, ""); + +#if __cplusplus >= 201402L + struct NonLiteral { + NonLiteral() {} + }; + NonLiteral nl; + constexpr NonLiteral &ExternNonLiteralVarDecl() { + extern NonLiteral nl; + return nl; + } + static_assert(&ExternNonLiteralVarDecl() == &nl, ""); +#endif } diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/Interp/vectors.cpp index 5c4694f122d812b6beae8f9a05670cb6e4ca52e3..49dae14fcf646f1e7b4fec1f641dc7e8b1be5893 100644 --- a/clang/test/AST/Interp/vectors.cpp +++ b/clang/test/AST/Interp/vectors.cpp @@ -8,6 +8,13 @@ static_assert(A[1] == 2, ""); // ref-error {{not an integral constant expression static_assert(A[2] == 3, ""); // ref-error {{not an integral constant expression}} static_assert(A[3] == 4, ""); // ref-error {{not an integral constant expression}} + +/// FIXME: It would be nice if the note said 'vector' instead of 'array'. +static_assert(A[12] == 4, ""); // ref-error {{not an integral constant expression}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}} + + /// VectorSplat casts typedef __attribute__(( ext_vector_type(4) )) float float4; constexpr float4 vec4_0 = (float4)0.5f; @@ -18,6 +25,19 @@ static_assert(vec4_0[3] == 0.5, ""); // ref-error {{not an integral constant exp constexpr int vec4_0_discarded = ((float4)12.0f, 0); +/// ImplicitValueInitExpr of vector type +constexpr float4 arr4[2] = { + {1,2,3,4}, +}; +static_assert(arr4[0][0] == 1, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[0][1] == 2, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[0][2] == 3, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[0][3] == 4, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} + /// From constant-expression-cxx11.cpp namespace Vector { diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp index da0011602a728e12508f32e6379e877e855b29be..68144e31a9304323af8f6303599e05d2c609cab2 100644 --- a/clang/test/AST/ast-dump-fpfeatures.cpp +++ b/clang/test/AST/ast-dump-fpfeatures.cpp @@ -1,10 +1,10 @@ // Test without serialization: -// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -ast-dump %s \ +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -ast-dump %s \ // RUN: | FileCheck --strict-whitespace %s // Test with serialization: -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s -// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \ +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -fcxx-exceptions -o %t %s +// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -fcxx-exceptions -ast-dump-all /dev/null \ // RUN: | sed -e "s/ //" -e "s/ imported//" \ // RUN: | FileCheck --strict-whitespace %s @@ -187,3 +187,65 @@ float func_18(float x, float y) { // CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward // CHECK: ReturnStmt // CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward + +#pragma float_control(precise, off) + +__attribute__((optnone)) +float func_19(float x, float y) { + return x + y; +} + +// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)' +// CHECK: CompoundStmt {{.*}} MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1 + +__attribute__((optnone)) +float func_20(float x, float y) try { + return x + y; +} catch (...) { + return 1.0; +} + +// CHECK-LABEL: FunctionDecl {{.*}} func_20 'float (float, float)' +// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1 + +struct C21 { + C21(float x, float y); + __attribute__((optnone)) float a_method(float x, float y) { + return x * y; + } + float member; +}; + +// CHECK-LABEL: CXXMethodDecl {{.*}} a_method 'float (float, float)' +// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} 'float' '*' ConstRoundingMode=downward MathErrno=1 + +__attribute__((optnone)) C21::C21(float x, float y) : member(x + y) {} + +// CHECK-LABEL: CXXConstructorDecl {{.*}} C21 'void (float, float)' +// CHECK: CXXCtorInitializer {{.*}} 'member' 'float' +// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1 + +template +__attribute__((optnone)) T func_22(T x, T y) { + return x + y; +} + +// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22 +// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)' +// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1 +// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)' +// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1 + +float func_23(float x, float y) { + return func_22(x, y); +} \ No newline at end of file diff --git a/clang/test/AST/ast-dump-fpfeatures.m b/clang/test/AST/ast-dump-fpfeatures.m new file mode 100644 index 0000000000000000000000000000000000000000..cf77529a75681173c16ca9af00be64ae32da4051 --- /dev/null +++ b/clang/test/AST/ast-dump-fpfeatures.m @@ -0,0 +1,29 @@ +// Test without serialization: +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -ast-dump %s \ +// RUN: | FileCheck --strict-whitespace %s + +// Test with serialization: +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s +// RUN: %clang_cc1 -x objective-c -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \ +// RUN: | sed -e "s/ //" -e "s/ imported//" \ +// RUN: | FileCheck --strict-whitespace %s + + +@interface Adder +- (float) sum: (float)x with: (float)y __attribute((optnone)); +@end + +#pragma float_control(precise, off) + +@implementation Adder +- (float) sum: (float)x with: (float)y __attribute((optnone)) { + return x + y; +} + +@end + +// CHECK-LABEL: ObjCImplementationDecl {{.*}} Adder +// CHECK: ObjCMethodDecl {{.*}} - sum:with: 'float' +// CHECK: CompoundStmt {{.*}} MathErrno=1 +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: BinaryOperator {{.*}} 'float' '+' MathErrno=1 diff --git a/clang/test/AST/ast-dump-late-parsing.cpp b/clang/test/AST/ast-dump-late-parsing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..760664efc5f142de0ac63c2ba8eaec29ca69612a --- /dev/null +++ b/clang/test/AST/ast-dump-late-parsing.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -ast-dump %s \ +// RUN: | FileCheck %s + +#pragma STDC FENV_ROUND FE_DOWNWARD +#pragma float_control(precise, off) + +template +__attribute__((optnone)) T func_22(T x, T y) { + return x + y; +} + +// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22 +// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)' +// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1 +// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)' +// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1 + +float func_23(float x, float y) { + return func_22(x, y); +} diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp index 8c03b58abb0edb6a81a290ff714e87441f0b07cf..cf740516db6f4b4e7d5b8459b7c8327835bc4d4c 100644 --- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp +++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp @@ -2725,7 +2725,25 @@ int main() // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "bool" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue" +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } @@ -3003,7 +3021,25 @@ int main() // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "bool" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue" +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-traits.cpp b/clang/test/AST/ast-dump-traits.cpp index 99ad50f528eb796b1c35ebcae705680f19f633d9..3085e5883fd2e2836eea3932b4edc7c73cb07dfc 100644 --- a/clang/test/AST/ast-dump-traits.cpp +++ b/clang/test/AST/ast-dump-traits.cpp @@ -40,10 +40,19 @@ void test_unary_expr_or_type_trait() { // CHECK-NEXT: | | `-EnumDecl {{.*}} col:8{{( imported)?}} referenced E // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_enum +// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'E' sugar +// CHECK-NEXT: | | `-EnumType {{.*}} 'E' +// CHECK-NEXT: | | `-Enum {{.*}} 'E' // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_same +// CHECK-NEXT: | | |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: | | `-BuiltinType {{.*}} 'float' // CHECK-NEXT: | `-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | `-TypeTraitExpr {{.*}} 'bool' __is_constructible +// CHECK-NEXT: |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: `-BuiltinType {{.*}} 'int' // CHECK-NEXT: |-FunctionDecl {{.*}} line:20:6{{( imported)?}} test_array_type_trait 'void ()' // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: | `-CStyleCastExpr {{.*}} 'void' diff --git a/clang/test/AST/bitint-suffix.cpp b/clang/test/AST/bitint-suffix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dab2b16c74235d3438381dec8dd3f144a940c96b --- /dev/null +++ b/clang/test/AST/bitint-suffix.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -ast-dump -Wno-unused %s | FileCheck --strict-whitespace %s + +// CHECK: FunctionDecl 0x{{[^ ]*}} <{{.*}}:[[@LINE+1]]:1, line:{{[0-9]*}}:1> line:[[@LINE+1]]:6 func 'void ()' +void func() { + // Ensure that we calculate the correct type from the literal suffix. + + // Note: 0__wb should create an _BitInt(2) because a signed bit-precise + // integer requires one bit for the sign and one bit for the value, + // at a minimum. + // CHECK: TypedefDecl 0x{{[^ ]*}} col:29 zero_wb 'typeof (0wb)':'_BitInt(2)' + typedef __typeof__(0__wb) zero_wb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 neg_zero_wb 'typeof (-0wb)':'_BitInt(2)' + typedef __typeof__(-0__wb) neg_zero_wb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:29 one_wb 'typeof (1wb)':'_BitInt(2)' + typedef __typeof__(1__wb) one_wb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 neg_one_wb 'typeof (-1wb)':'_BitInt(2)' + typedef __typeof__(-1__wb) neg_one_wb; + + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 zero_uwb 'typeof (0uwb)':'unsigned _BitInt(1)' + typedef __typeof__(0__uwb) zero_uwb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:31 neg_zero_uwb 'typeof (-0uwb)':'unsigned _BitInt(1)' + typedef __typeof__(-0__uwb) neg_zero_uwb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 one_uwb 'typeof (1uwb)':'unsigned _BitInt(1)' + typedef __typeof__(1__uwb) one_uwb; + + // Try a value that is too large to fit in [u]intmax_t. + + // CHECK: TypedefDecl 0x{{[^ ]*}} col:49 huge_uwb 'typeof (18446744073709551616uwb)':'unsigned _BitInt(65)' + typedef __typeof__(18446744073709551616__uwb) huge_uwb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:48 huge_wb 'typeof (18446744073709551616wb)':'_BitInt(66)' + typedef __typeof__(18446744073709551616__wb) huge_wb; +} diff --git a/clang/test/Analysis/gh-issue-89185.c b/clang/test/Analysis/gh-issue-89185.c new file mode 100644 index 0000000000000000000000000000000000000000..8a907f198a5fd5321e03ba061ef708cf0df6011c --- /dev/null +++ b/clang/test/Analysis/gh-issue-89185.c @@ -0,0 +1,14 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_dump(char); +void clang_analyzer_dump_ptr(char*); + +// https://github.com/llvm/llvm-project/issues/89185 +void binding_to_label_loc() { + char *b = &&MyLabel; +MyLabel: + *b = 0; // no-crash + clang_analyzer_dump_ptr(b); // expected-warning {{&&MyLabel}} + clang_analyzer_dump(*b); // expected-warning {{Unknown}} + // FIXME: We should never reach here, as storing to a label is invalid. +} diff --git a/clang/test/ClangScanDeps/modules-full.cpp b/clang/test/ClangScanDeps/modules-full.cpp index 59efef0ecbaa64fce41cfe3b474d1642e6718055..a00a431eb56911ca52c740ece5254ca364bcf9ae 100644 --- a/clang/test/ClangScanDeps/modules-full.cpp +++ b/clang/test/ClangScanDeps/modules-full.cpp @@ -33,6 +33,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-emit-module" +// CHECK: "-fno-modules-prune-non-affecting-module-map-files" // CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H2_DINCLUDE]]/header2-{{[A-Z0-9]+}}.pcm" // CHECK-NOT: "-fimplicit-module-maps" // CHECK: "-fmodule-name=header1" @@ -51,6 +52,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1", // CHECK: "-emit-module", +// CHECK: "-fno-modules-prune-non-affecting-module-map-files" // CHECK-NOT: "-fimplicit-module-maps", // CHECK: "-fmodule-name=header1", // CHECK: "-fno-implicit-modules", @@ -68,6 +70,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1", // CHECK: "-emit-module", +// CHECK: "-fno-modules-prune-non-affecting-module-map-files" // CHECK: "-fmodule-name=header2", // CHECK-NOT: "-fimplicit-module-maps", // CHECK: "-fno-implicit-modules", diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c b/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c index 51585f27e0bc70d6e76cfccc25b4b02efdaf5b73..eeb13b097819cdba0b055f16b577eaa44158f316 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c @@ -1,6 +1,6 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -target-feature +altivec -target-feature +htm -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s -// RUN: not %clang_cc1 -target-feature +altivec -target-feature -htm -triple powerpc64-unknown-unknown -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=ERROR +// RUN: not %clang_cc1 -target-feature +altivec -target-feature -htm -triple powerpc64-unknown-unknown -emit-llvm-only %s 2>&1 | FileCheck %s --check-prefix=ERROR void test1(long int *r, int code, long int *a, long int *b) { // CHECK-LABEL: define{{.*}} void @test1 diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c b/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c index f5149bf4ce8fda723c2551df55ca61df143d17db..485ef84df086b7a64feceecd8ac2539011caea5a 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c @@ -1,17 +1,17 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_SI +// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_SI // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_F +// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_F // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_SLL +// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_SLL // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_D +// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_D // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_UNALIGNED_UI +// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_UNALIGNED_UI // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify +// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify #include diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c index b303d71304bf3ece9b14905e395618055f66a48a..66d15a7d1bc052a602522bc937d4d2e4113e3737 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c @@ -1,6 +1,6 @@ // REQUIRES: riscv-registered-target // RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \ -// RUN: -emit-llvm %s 2>&1 | FileCheck %s +// RUN: -emit-llvm-only %s 2>&1 | FileCheck %s #include diff --git a/clang/test/CodeGen/attr-counted-by-pr88931.c b/clang/test/CodeGen/attr-counted-by-pr88931.c new file mode 100644 index 0000000000000000000000000000000000000000..cc3d751c7c6d83823fc22ad829a5cb6a44814b0e --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-pr88931.c @@ -0,0 +1,40 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wno-missing-declarations -emit-llvm -o - %s | FileCheck %s + +struct foo { + int x,y,z; + struct bar { + int count; + int array[] __attribute__((counted_by(count))); + }; +}; + +void init(void * __attribute__((pass_dynamic_object_size(0)))); + +// CHECK-LABEL: define dso_local void @test1( +// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4 +// CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef -1) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: ret void +// +void test1(struct bar *p) { + init(p->array); +} + +struct mux { + int count; + int array[] __attribute__((counted_by(count))); +}; + +struct bux { struct mux x; }; + +// CHECK-LABEL: define dso_local void @test2( +// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @init(ptr noundef [[P]], i64 noundef -1) #[[ATTR2]] +// CHECK-NEXT: ret void +// +void test2(struct bux *p) { + init(p); +} diff --git a/clang/test/CodeGen/attr-counted-by-pr88931.cpp b/clang/test/CodeGen/attr-counted-by-pr88931.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a8cc1d07e50d9acc22ec64cb92b04e455f0e37c --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-pr88931.cpp @@ -0,0 +1,21 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -emit-llvm -o - %s | FileCheck %s + +struct foo { + struct bar { + int array[]; + bar(); + }; +}; + +void init(void * __attribute__((pass_dynamic_object_size(0)))); + +// CHECK-LABEL: define dso_local void @_ZN3foo3barC1Ev( +// CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(1) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] align 2 { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @_Z4initPvU25pass_dynamic_object_size0(ptr noundef nonnull [[THIS]], i64 noundef -1) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: ret void +// +foo::bar::bar() { + init(array); +} diff --git a/clang/test/CodeGen/pgo-force-function-attrs.ll b/clang/test/CodeGen/pgo-force-function-attrs.ll new file mode 100644 index 0000000000000000000000000000000000000000..3e9ea95e4df410db9f897991398d23ede9f69b23 --- /dev/null +++ b/clang/test/CodeGen/pgo-force-function-attrs.ll @@ -0,0 +1,12 @@ +; RUN: %clang_cc1 -O2 -mllvm -pgo-cold-func-opt=optsize -mllvm -enable-pgo-force-function-attrs -fprofile-sample-use=%S/Inputs/pgo-sample.prof %s -emit-llvm -o - | FileCheck %s --check-prefix=OPTSIZE +; Check that no profile means no optsize +; RUN: %clang_cc1 -O2 -mllvm -pgo-cold-func-opt=optsize -mllvm -enable-pgo-force-function-attrs %s -emit-llvm -o - | FileCheck %s --check-prefix=NONE +; Check that no -pgo-cold-func-opt=optsize means no optsize +; RUN: %clang_cc1 -O2 -mllvm -enable-pgo-force-function-attrs -fprofile-sample-use=%S/Inputs/pgo-sample.prof %s -emit-llvm -o - | FileCheck %s --check-prefix=NONE + +; NONE-NOT: optsize +; OPTSIZE: optsize + +define void @f() cold { + ret void +} diff --git a/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7592cec5da776dea7aed148f86a1f4b2b66d78a --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -emit-llvm -mconstructor-aliases -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fclang-abi-compat=18 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=CLANG18 %s +// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=MSABI %s + + +class func { +public: + template + func(T){}; + template + func(T, U){}; +}; + +void GH88906(){ + class Test{ + public: + func a{[]{ }, []{ }}; + func b{[]{ }}; + func c{[]{ }}; + } test; +} + +// CHECK-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev +// CHECK: call void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_ +// CHECK: call void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_ +// CHECK: call void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_ + +// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_ +// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_ +// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_ + +// CLANG18-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev +// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EZ7GH88906vENS1_UlvE0_EEET_T0_ +// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_ +// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_ + + + +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??0Test@?1??GH88906@@YAXXZ@QAE@XZ" +// MSABI: call x86_thiscallcc noundef ptr @"??$?0V@a@Test@?1??GH88906@@YAXXZ@V@12?1??3@YAXXZ@@func@@QAE@V@a@Test@?1??GH88906@@YAXXZ@V@23?1??4@YAXXZ@@Z" +// MSABI: call x86_thiscallcc noundef ptr @"??$?0V@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@b@Test@?1??GH88906@@YAXXZ@@Z" +// MSABI: call x86_thiscallcc noundef ptr @"??$?0V@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@c@Test@?1??GH88906@@YAXXZ@@Z" + +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V@a@Test@?1??GH88906@@YAXXZ@V@12?1??3@YAXXZ@@func@@QAE@V@a@Test@?1??GH88906@@YAXXZ@V@23?1??4@YAXXZ@@Z" +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@b@Test@?1??GH88906@@YAXXZ@@Z" +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@c@Test@?1??GH88906@@YAXXZ@@Z" diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp index 75851d8805bb6e37d1308bcf7e6b03c112f87137..65bfb099468817961b14782fd0b20cc62f48fc52 100644 --- a/clang/test/CodeGenCoroutines/coro-await.cpp +++ b/clang/test/CodeGenCoroutines/coro-await.cpp @@ -73,7 +73,7 @@ extern "C" void f0() { // --------------------------- // Call coro.await.suspend // --------------------------- - // CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f0_await) + // CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @f0.__await_suspend_wrapper__await) // ------------------------- // Generate a suspend point: // ------------------------- @@ -100,7 +100,7 @@ extern "C" void f0() { // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true) // Await suspend wrapper - // CHECK: define{{.*}} @__await_suspend_wrapper_f0_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) + // CHECK: define{{.*}} @f0.__await_suspend_wrapper__await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]], // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]], // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]] @@ -149,7 +149,7 @@ extern "C" void f1(int) { // --------------------------- // Call coro.await.suspend // --------------------------- - // CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f1_yield) + // CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @f1.__await_suspend_wrapper__yield) // ------------------------------------------- // See if await_suspend decided not to suspend // ------------------------------------------- @@ -162,7 +162,7 @@ extern "C" void f1(int) { // CHECK: call void @_ZN13suspend_maybe12await_resumeEv(ptr {{[^,]*}} %[[AWAITABLE]]) // Await suspend wrapper - // CHECK: define {{.*}} i1 @__await_suspend_wrapper_f1_yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) + // CHECK: define {{.*}} i1 @f1.__await_suspend_wrapper__yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]], // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]], // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]] @@ -370,7 +370,7 @@ extern "C" void TestTailcall() { // --------------------------- // Call coro.await.suspend // --------------------------- - // CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_TestTailcall_await) + // CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @TestTailcall.__await_suspend_wrapper__await) // CHECK-NEXT: call void @llvm.coro.resume(ptr %[[RESUMED]]) // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false) // CHECK-NEXT: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [ @@ -379,7 +379,7 @@ extern "C" void TestTailcall() { // CHECK-NEXT: ] // Await suspend wrapper - // CHECK: define {{.*}} ptr @__await_suspend_wrapper_TestTailcall_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) + // CHECK: define {{.*}} ptr @TestTailcall.__await_suspend_wrapper__await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]], // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]], // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]] diff --git a/clang/test/CodeGenCoroutines/coro-dwarf.cpp b/clang/test/CodeGenCoroutines/coro-dwarf.cpp index 2c9c827e6753d68e8a0e71449b896ab2df1ee453..f951b63dc117c3f199e86f8775f8141921aa41f1 100644 --- a/clang/test/CodeGenCoroutines/coro-dwarf.cpp +++ b/clang/test/CodeGenCoroutines/coro-dwarf.cpp @@ -71,14 +71,14 @@ void f_coro(int val, MoveOnly moParam, MoveAndCopy mcParam) { // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "mcParam", arg: 3, scope: ![[SP]], file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "__promise", -// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_init" +// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "_Z6f_coroi8MoveOnly11MoveAndCopy.__await_suspend_wrapper__init" // CHECK-NEXT: !{{[0-9]+}} = !DIFile // CHECK-NEXT: !{{[0-9]+}} = !DISubroutineType // CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1, // CHECK-NEXT: !{{[0-9]+}} = !DILocation // CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2, -// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_final" +// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "_Z6f_coroi8MoveOnly11MoveAndCopy.__await_suspend_wrapper__final" // CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1, // CHECK-NEXT: !{{[0-9]+}} = !DILocation // CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2, diff --git a/clang/test/CodeGenCoroutines/pr65054.cpp b/clang/test/CodeGenCoroutines/pr65054.cpp index 7af9c04fca180e725cdf8fe58bf47d60416e1bcf..2d8b6dfe18d5521aa0e9ee810f7021be921ac9d3 100644 --- a/clang/test/CodeGenCoroutines/pr65054.cpp +++ b/clang/test/CodeGenCoroutines/pr65054.cpp @@ -48,6 +48,6 @@ MyTask FooBar() { } // CHECK-O0: define{{.*}}@_Z6FooBarv.resume -// CHECK-O0: call{{.*}}@__await_suspend_wrapper__Z6FooBarv_await( +// CHECK-O0: call{{.*}}@_Z6FooBarv.__await_suspend_wrapper__await( // CHECK-O0-NOT: store // CHECK-O0: ret void diff --git a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl index 2fd5a19fc33521641ef04a378b33eef7586f36a6..cdc9abbd70e40bb926a4257e78abb6e94b779e96 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s // CHECK-LABEL: builtin_lerp_half_vector -// CHECK: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// CHECK: ret <3 x half> %dx.lerp +// CHECK: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// CHECK: ret <3 x half> %hlsl.lerp half3 builtin_lerp_half_vector (half3 p0) { return __builtin_hlsl_lerp ( p0, p0, p0 ); } // CHECK-LABEL: builtin_lerp_floar_vector -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.lerp +// CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.lerp float2 builtin_lerp_floar_vector ( float2 p0) { return __builtin_hlsl_lerp ( p0, p0, p0 ); } diff --git a/clang/test/CodeGenHLSL/builtins/lerp.hlsl b/clang/test/CodeGenHLSL/builtins/lerp.hlsl index 49cd04a10115aee13f70700baddee400b6013d62..634b20be3a28d6d1a005ae8952d8fb121890f9a9 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp.hlsl @@ -1,69 +1,92 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF,DXIL_NO_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_NO_HALF,SPIR_CHECK -// NATIVE_HALF: %dx.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) -// NATIVE_HALF: ret half %dx.lerp -// NO_HALF: %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) -// NO_HALF: ret float %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call half @llvm.spv.lerp.f16(half %0, half %1, half %2) +// NATIVE_HALF: ret half %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) +// SPIR_NO_HALF: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) +// NO_HALF: ret float %hlsl.lerp half test_lerp_half(half p0) { return lerp(p0, p0, p0); } -// NATIVE_HALF: %dx.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) -// NATIVE_HALF: ret <2 x half> %dx.lerp -// NO_HALF: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// NO_HALF: ret <2 x float> %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.spv.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// NATIVE_HALF: ret <2 x half> %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// SPIR_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// NO_HALF: ret <2 x float> %hlsl.lerp half2 test_lerp_half2(half2 p0) { return lerp(p0, p0, p0); } -// NATIVE_HALF: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// NATIVE_HALF: ret <3 x half> %dx.lerp -// NO_HALF: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// NO_HALF: ret <3 x float> %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.spv.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// NATIVE_HALF: ret <3 x half> %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// SPIR_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// NO_HALF: ret <3 x float> %hlsl.lerp half3 test_lerp_half3(half3 p0) { return lerp(p0, p0, p0); } -// NATIVE_HALF: %dx.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) -// NATIVE_HALF: ret <4 x half> %dx.lerp -// NO_HALF: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// NO_HALF: ret <4 x float> %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.spv.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// NATIVE_HALF: ret <4 x half> %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// SPIR_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// NO_HALF: ret <4 x float> %hlsl.lerp half4 test_lerp_half4(half4 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) -// CHECK: ret float %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) +// SPIR_CHECK: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) +// CHECK: ret float %hlsl.lerp float test_lerp_float(float p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2(float2 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3(float3 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.lerp float4 test_lerp_float4(float4 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2_splat(float p0, float2 p1) { return lerp(p0, p1, p1); } -// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3_splat(float p0, float3 p1) { return lerp(p0, p1, p1); } -// CHECK: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.lerp float4 test_lerp_float4_splat(float p0, float4 p1) { return lerp(p0, p1, p1); } // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) -// CHECK: ret <2 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2_int_splat(float2 p0, int p1) { return lerp(p0, p0, p1); } @@ -71,8 +94,9 @@ float2 test_lerp_float2_int_splat(float2 p0, int p1) { // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) -// CHECK: ret <3 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3_int_splat(float3 p0, int p1) { return lerp(p0, p0, p1); } diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl index 749eac6d64736d476ee76b4c12648f08de4de091..bd4f38067a5c59fe50bbd6bb76e8961ae4ee38df 100644 --- a/clang/test/CodeGenHLSL/builtins/mad.hlsl +++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl @@ -1,182 +1,238 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF + +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_CHECK #ifdef __HLSL_ENABLE_16_BIT -// NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %0, i16 %1, i16 %2) -// NATIVE_HALF: ret i16 %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %0, i16 %1, i16 %2) +// DXIL_NATIVE_HALF: ret i16 %dx.umad +// SPIR_NATIVE_HALF: mul nuw i16 %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw i16 %{{.*}}, %{{.*}} uint16_t test_mad_uint16_t(uint16_t p0, uint16_t p1, uint16_t p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.umad = call <2 x i16> @llvm.dx.umad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) -// NATIVE_HALF: ret <2 x i16> %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call <2 x i16> @llvm.dx.umad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) +// DXIL_NATIVE_HALF: ret <2 x i16> %dx.umad +// SPIR_NATIVE_HALF: mul nuw <2 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw <2 x i16> %{{.*}}, %{{.*}} uint16_t2 test_mad_uint16_t2(uint16_t2 p0, uint16_t2 p1, uint16_t2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.umad = call <3 x i16> @llvm.dx.umad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) -// NATIVE_HALF: ret <3 x i16> %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call <3 x i16> @llvm.dx.umad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) +// DXIL_NATIVE_HALF: ret <3 x i16> %dx.umad +// SPIR_NATIVE_HALF: mul nuw <3 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw <3 x i16> %{{.*}}, %{{.*}} uint16_t3 test_mad_uint16_t3(uint16_t3 p0, uint16_t3 p1, uint16_t3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.umad = call <4 x i16> @llvm.dx.umad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) -// NATIVE_HALF: ret <4 x i16> %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call <4 x i16> @llvm.dx.umad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) +// DXIL_NATIVE_HALF: ret <4 x i16> %dx.umad +// SPIR_NATIVE_HALF: mul nuw <4 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw <4 x i16> %{{.*}}, %{{.*}} uint16_t4 test_mad_uint16_t4(uint16_t4 p0, uint16_t4 p1, uint16_t4 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %0, i16 %1, i16 %2) -// NATIVE_HALF: ret i16 %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %0, i16 %1, i16 %2) +// DXIL_NATIVE_HALF: ret i16 %dx.imad +// SPIR_NATIVE_HALF: mul nsw i16 %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw i16 %{{.*}}, %{{.*}} int16_t test_mad_int16_t(int16_t p0, int16_t p1, int16_t p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call <2 x i16> @llvm.dx.imad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) -// NATIVE_HALF: ret <2 x i16> %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call <2 x i16> @llvm.dx.imad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) +// DXIL_NATIVE_HALF: ret <2 x i16> %dx.imad +// SPIR_NATIVE_HALF: mul nsw <2 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw <2 x i16> %{{.*}}, %{{.*}} int16_t2 test_mad_int16_t2(int16_t2 p0, int16_t2 p1, int16_t2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call <3 x i16> @llvm.dx.imad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) -// NATIVE_HALF: ret <3 x i16> %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call <3 x i16> @llvm.dx.imad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) +// DXIL_NATIVE_HALF: ret <3 x i16> %dx.imad +// SPIR_NATIVE_HALF: mul nsw <3 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw <3 x i16> %{{.*}}, %{{.*}} int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call <4 x i16> @llvm.dx.imad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) -// NATIVE_HALF: ret <4 x i16> %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call <4 x i16> @llvm.dx.imad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) +// DXIL_NATIVE_HALF: ret <4 x i16> %dx.imad +// SPIR_NATIVE_HALF: mul nsw <4 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw <4 x i16> %{{.*}}, %{{.*}} int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p0, p1, p2); } #endif // __HLSL_ENABLE_16_BIT -// NATIVE_HALF: %dx.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) -// NATIVE_HALF: ret half %dx.fmad -// NO_HALF: %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) -// NO_HALF: ret float %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) +// NATIVE_HALF: ret half %hlsl.fmad +// NO_HALF: %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +// NO_HALF: ret float %hlsl.fmad half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.fmad = call <2 x half> @llvm.fmuladd.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) -// NATIVE_HALF: ret <2 x half> %dx.fmad -// NO_HALF: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// NO_HALF: ret <2 x float> %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call <2 x half> @llvm.fmuladd.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// NATIVE_HALF: ret <2 x half> %hlsl.fmad +// NO_HALF: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// NO_HALF: ret <2 x float> %hlsl.fmad half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.fmad = call <3 x half> @llvm.fmuladd.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// NATIVE_HALF: ret <3 x half> %dx.fmad -// NO_HALF: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// NO_HALF: ret <3 x float> %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call <3 x half> @llvm.fmuladd.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// NATIVE_HALF: ret <3 x half> %hlsl.fmad +// NO_HALF: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// NO_HALF: ret <3 x float> %hlsl.fmad half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.fmad = call <4 x half> @llvm.fmuladd.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) -// NATIVE_HALF: ret <4 x half> %dx.fmad -// NO_HALF: %dx.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// NO_HALF: ret <4 x float> %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call <4 x half> @llvm.fmuladd.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// NATIVE_HALF: ret <4 x half> %hlsl.fmad +// NO_HALF: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// NO_HALF: ret <4 x float> %hlsl.fmad half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) -// CHECK: ret float %dx.fmad +// CHECK: %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +// CHECK: ret float %hlsl.fmad float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.fmad float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) -// CHECK: ret double %dx.fmad +// CHECK: %hlsl.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) +// CHECK: ret double %hlsl.fmad double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %0, <2 x double> %1, <2 x double> %2) -// CHECK: ret <2 x double> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %0, <2 x double> %1, <2 x double> %2) +// CHECK: ret <2 x double> %hlsl.fmad double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <3 x double> @llvm.fmuladd.v3f64(<3 x double> %0, <3 x double> %1, <3 x double> %2) -// CHECK: ret <3 x double> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x double> @llvm.fmuladd.v3f64(<3 x double> %0, <3 x double> %1, <3 x double> %2) +// CHECK: ret <3 x double> %hlsl.fmad double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %0, <4 x double> %1, <4 x double> %2) -// CHECK: ret <4 x double> %dx.fmad +// CHECK: %hlsl.fmad = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %0, <4 x double> %1, <4 x double> %2) +// CHECK: ret <4 x double> %hlsl.fmad double4 test_mad_double4(double4 p0, double4 p1, double4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %0, i32 %1, i32 %2) -// CHECK: ret i32 %dx.imad +// DXIL_CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %0, i32 %1, i32 %2) +// DXIL_CHECK: ret i32 %dx.imad +// SPIR_CHECK: mul nsw i32 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw i32 %{{.*}}, %{{.*}} int test_mad_int(int p0, int p1, int p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <2 x i32> @llvm.dx.imad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) -// CHECK: ret <2 x i32> %dx.imad +// DXIL_CHECK: %dx.imad = call <2 x i32> @llvm.dx.imad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) +// DXIL_CHECK: ret <2 x i32> %dx.imad +// SPIR_CHECK: mul nsw <2 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <2 x i32> %{{.*}}, %{{.*}} int2 test_mad_int2(int2 p0, int2 p1, int2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <3 x i32> @llvm.dx.imad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) -// CHECK: ret <3 x i32> %dx.imad +// DXIL_CHECK: %dx.imad = call <3 x i32> @llvm.dx.imad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) +// DXIL_CHECK: ret <3 x i32> %dx.imad +// SPIR_CHECK: mul nsw <3 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <3 x i32> %{{.*}}, %{{.*}} int3 test_mad_int3(int3 p0, int3 p1, int3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <4 x i32> @llvm.dx.imad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) -// CHECK: ret <4 x i32> %dx.imad +// DXIL_CHECK: %dx.imad = call <4 x i32> @llvm.dx.imad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) +// DXIL_CHECK: ret <4 x i32> %dx.imad +// SPIR_CHECK: mul nsw <4 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <4 x i32> %{{.*}}, %{{.*}} int4 test_mad_int4(int4 p0, int4 p1, int4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %0, i64 %1, i64 %2) -// CHECK: ret i64 %dx.imad +// DXIL_CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %0, i64 %1, i64 %2) +// DXIL_CHECK: ret i64 %dx.imad +// SPIR_CHECK: mul nsw i64 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw i64 %{{.*}}, %{{.*}} int64_t test_mad_int64_t(int64_t p0, int64_t p1, int64_t p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <2 x i64> @llvm.dx.imad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) -// CHECK: ret <2 x i64> %dx.imad +// DXIL_CHECK: %dx.imad = call <2 x i64> @llvm.dx.imad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) +// DXIL_CHECK: ret <2 x i64> %dx.imad +// SPIR_CHECK: mul nsw <2 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <2 x i64> %{{.*}}, %{{.*}} int64_t2 test_mad_int64_t2(int64_t2 p0, int64_t2 p1, int64_t2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <3 x i64> @llvm.dx.imad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) -// CHECK: ret <3 x i64> %dx.imad +// DXIL_CHECK: %dx.imad = call <3 x i64> @llvm.dx.imad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) +// DXIL_CHECK: ret <3 x i64> %dx.imad +// SPIR_CHECK: mul nsw <3 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <3 x i64> %{{.*}}, %{{.*}} int64_t3 test_mad_int64_t3(int64_t3 p0, int64_t3 p1, int64_t3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <4 x i64> @llvm.dx.imad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) -// CHECK: ret <4 x i64> %dx.imad +// DXIL_CHECK: %dx.imad = call <4 x i64> @llvm.dx.imad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) +// DXIL_CHECK: ret <4 x i64> %dx.imad +// SPIR_CHECK: mul nsw <4 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <4 x i64> %{{.*}}, %{{.*}} int64_t4 test_mad_int64_t4(int64_t4 p0, int64_t4 p1, int64_t4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %0, i32 %1, i32 %2) -// CHECK: ret i32 %dx.umad +// DXIL_CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %0, i32 %1, i32 %2) +// DXIL_CHECK: ret i32 %dx.umad +// SPIR_CHECK: mul nuw i32 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw i32 %{{.*}}, %{{.*}} uint test_mad_uint(uint p0, uint p1, uint p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <2 x i32> @llvm.dx.umad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) -// CHECK: ret <2 x i32> %dx.umad +// DXIL_CHECK: %dx.umad = call <2 x i32> @llvm.dx.umad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) +// DXIL_CHECK: ret <2 x i32> %dx.umad +// SPIR_CHECK: mul nuw <2 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <2 x i32> %{{.*}}, %{{.*}} uint2 test_mad_uint2(uint2 p0, uint2 p1, uint2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <3 x i32> @llvm.dx.umad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) -// CHECK: ret <3 x i32> %dx.umad +// DXIL_CHECK: %dx.umad = call <3 x i32> @llvm.dx.umad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) +// DXIL_CHECK: ret <3 x i32> %dx.umad +// SPIR_CHECK: mul nuw <3 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <3 x i32> %{{.*}}, %{{.*}} uint3 test_mad_uint3(uint3 p0, uint3 p1, uint3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <4 x i32> @llvm.dx.umad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) -// CHECK: ret <4 x i32> %dx.umad +// DXIL_CHECK: %dx.umad = call <4 x i32> @llvm.dx.umad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) +// DXIL_CHECK: ret <4 x i32> %dx.umad +// SPIR_CHECK: mul nuw <4 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <4 x i32> %{{.*}}, %{{.*}} uint4 test_mad_uint4(uint4 p0, uint4 p1, uint4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %0, i64 %1, i64 %2) -// CHECK: ret i64 %dx.umad +// DXIL_CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %0, i64 %1, i64 %2) +// DXIL_CHECK: ret i64 %dx.umad +// SPIR_CHECK: mul nuw i64 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw i64 %{{.*}}, %{{.*}} uint64_t test_mad_uint64_t(uint64_t p0, uint64_t p1, uint64_t p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <2 x i64> @llvm.dx.umad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) -// CHECK: ret <2 x i64> %dx.umad +// DXIL_CHECK: %dx.umad = call <2 x i64> @llvm.dx.umad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) +// DXIL_CHECK: ret <2 x i64> %dx.umad +// SPIR_CHECK: mul nuw <2 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <2 x i64> %{{.*}}, %{{.*}} uint64_t2 test_mad_uint64_t2(uint64_t2 p0, uint64_t2 p1, uint64_t2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <3 x i64> @llvm.dx.umad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) -// CHECK: ret <3 x i64> %dx.umad +// DXIL_CHECK: %dx.umad = call <3 x i64> @llvm.dx.umad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) +// DXIL_CHECK: ret <3 x i64> %dx.umad +// SPIR_CHECK: mul nuw <3 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <3 x i64> %{{.*}}, %{{.*}} uint64_t3 test_mad_uint64_t3(uint64_t3 p0, uint64_t3 p1, uint64_t3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <4 x i64> @llvm.dx.umad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) -// CHECK: ret <4 x i64> %dx.umad +// DXIL_CHECK: %dx.umad = call <4 x i64> @llvm.dx.umad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) +// DXIL_CHECK: ret <4 x i64> %dx.umad +// SPIR_CHECK: mul nuw <4 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <4 x i64> %{{.*}}, %{{.*}} uint64_t4 test_mad_uint64_t4(uint64_t4 p0, uint64_t4 p1, uint64_t4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2_splat(float p0, float2 p1, float2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3_splat(float p0, float3 p1, float3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.fmad float4 test_mad_float4_splat(float p0, float4 p1, float4 p2) { return mad(p0, p1, p2); } // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) -// CHECK: ret <2 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) { return mad(p0, p1, p2); } @@ -184,8 +240,8 @@ float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) { // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) -// CHECK: ret <3 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3_int_splat(float3 p0, float3 p1, int p2) { return mad(p0, p1, p2); } diff --git a/clang/test/CoverageMapping/statement-expression.c b/clang/test/CoverageMapping/statement-expression.c new file mode 100644 index 0000000000000000000000000000000000000000..5f9ab5838af3423f6a45ab445d8c4b36997177a4 --- /dev/null +++ b/clang/test/CoverageMapping/statement-expression.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name statement-expression.c %s + +// No crash for the following examples, where GNU Statement Expression extension +// could introduce region terminators (break, goto etc) before implicit +// initializers in a struct or an array. +// See https://github.com/llvm/llvm-project/pull/89564 + +struct Foo { + int field1; + int field2; +}; + +void f1(void) { + struct Foo foo = { + .field1 = ({ + switch (0) { + case 0: + break; // A region terminator + } + 0; + }), + // ImplicitValueInitExpr introduced here for .field2 + }; +} + +void f2(void) { + int arr[3] = { + [0] = ({ + goto L0; // A region terminator +L0: + 0; + }), + // ImplicitValueInitExpr introduced here for subscript [1] + [2] = 0, + }; +} diff --git a/clang/test/Driver/aix-small-local-exec-tls.c b/clang/test/Driver/aix-small-local-exec-dynamic-tls.c similarity index 50% rename from clang/test/Driver/aix-small-local-exec-tls.c rename to clang/test/Driver/aix-small-local-exec-dynamic-tls.c index e6719502a3babc33fb3ac25864c75027163f917e..e8ee07bff35f5da753a67a095131fcb641e14708 100644 --- a/clang/test/Driver/aix-small-local-exec-tls.c +++ b/clang/test/Driver/aix-small-local-exec-dynamic-tls.c @@ -6,6 +6,9 @@ // RUN: %clang -target powerpc64-unknown-aix -maix-small-local-exec-tls -S -emit-llvm \ // RUN: %s -o - | FileCheck %s --check-prefix=CHECK-AIX_SMALL_LOCALEXEC_TLS +// RUN: %clang -target powerpc64-unknown-aix -maix-small-local-dynamic-tls -S -emit-llvm \ +// RUN: %s -o - | FileCheck %s --check-prefix=CHECK-AIX_SMALL_LOCALDYNAMIC_TLS + // RUN: not %clang -target powerpc-unknown-aix -maix-small-local-exec-tls \ // RUN: -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-UNSUPPORTED-AIX32 %s // RUN: not %clang -target powerpc64le-unknown-linux-gnu -maix-small-local-exec-tls \ @@ -19,19 +22,35 @@ // RUN: -fsyntax-only -fno-data-sections %s 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s +// RUN: not %clang -target powerpc-unknown-aix -maix-small-local-dynamic-tls \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-UNSUPPORTED-AIX32 %s +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -maix-small-local-dynamic-tls \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-UNSUPPORTED-LINUX %s +// RUN: not %clang -target powerpc64-unknown-linux-gnu -maix-small-local-dynamic-tls \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-UNSUPPORTED-LINUX %s +// RUN: not %clang -target powerpc64-unknown-aix -maix-small-local-dynamic-tls \ +// RUN: -fsyntax-only -fno-data-sections %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s +// RUN: not %clang -target powerpc64-unknown-linux-gnu -maix-small-local-dynamic-tls \ +// RUN: -fsyntax-only -fno-data-sections %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s + int test(void) { return 0; } // CHECK: test() #0 { // CHECK: attributes #0 = { -// CHECK-SAME: -aix-small-local-exec-tls +// CHECK-SAME: {{-aix-small-local-exec-tls,.*-aix-small-local-dynamic-tls|-aix-small-local-dynamic-tls,.*-aix-small-local-exec-tls}} -// CHECK-UNSUPPORTED-AIX32: option '-maix-small-local-exec-tls' cannot be specified on this target -// CHECK-UNSUPPORTED-LINUX: option '-maix-small-local-exec-tls' cannot be specified on this target -// CHECK-UNSUPPORTED-NO-DATASEC: invalid argument '-maix-small-local-exec-tls' only allowed with '-fdata-sections' +// CHECK-UNSUPPORTED-AIX32: option '-maix-small-local-[exec|dynamic]-tls' cannot be specified on this target +// CHECK-UNSUPPORTED-LINUX: option '-maix-small-local-[exec|dynamic]-tls' cannot be specified on this target +// CHECK-UNSUPPORTED-NO-DATASEC: invalid argument '-maix-small-local-[exec|dynamic]-tls' only allowed with '-fdata-sections' // CHECK-AIX_SMALL_LOCALEXEC_TLS: test() #0 { // CHECK-AIX_SMALL_LOCALEXEC_TLS: attributes #0 = { // CHECK-AIX_SMALL_LOCALEXEC_TLS-SAME: +aix-small-local-exec-tls +// CHECK-AIX_SMALL_LOCALDYNAMIC_TLS: test() #0 { +// CHECK-AIX_SMALL_LOCALDYNAMIC_TLS: attributes #0 = { +// CHECK-AIX_SMALL_LOCALDYNAMIC_TLS-SAME: +aix-small-local-dynamic-tls diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 5b6dfe308a76eae703bc216db2410369ae59e6d4..75f49deca0653d556d53f462211c007c80554bf6 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -70,12 +70,16 @@ // fsanitize_address: -fsanitize=address // RUN: %clang_cl -### /FA -fprofile-instr-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE %s +// RUN: %clang_cl -### /FA -fprofile-instr-generate -fno-rtlib-defaultlib -frtlib-defaultlib -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE %s // RUN: %clang_cl -### /FA -fprofile-instr-generate=/tmp/somefile.profraw -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-FILE %s // RUN: %clang_cl -### /FAcsu -fprofile-instr-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE %s // RUN: %clang_cl -### /FAcsu -fprofile-instr-generate=/tmp/somefile.profraw -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-FILE %s // CHECK-PROFILE-INSTR-GENERATE: "-fprofile-instrument=clang" "--dependent-lib=clang_rt.profile{{[^"]*}}.lib" // CHECK-PROFILE-INSTR-GENERATE-FILE: "-fprofile-instrument-path=/tmp/somefile.profraw" +// RUN: %clang_cl -### /FA -fprofile-instr-generate -fno-rtlib-defaultlib -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-NODEF %s +// CHECK-PROFILE-INSTR-GENERATE-NODEF-NOT: "--dependent-lib=clang_rt.profile{{[^"]*}}.lib" + // RUN: %clang_cl -### /FA -fprofile-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // RUN: %clang_cl -### /FAcsu -fprofile-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // CHECK-PROFILE-GENERATE: "-fprofile-instrument=llvm" "--dependent-lib=clang_rt.profile{{[^"]*}}.lib" @@ -790,6 +794,7 @@ // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC %s // ARM64EC-NOT: /arm64EC has been overridden by specified target // ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.33.0" +// ARM64EC-SAME: "--dependent-lib=softintrin" // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s // ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c index 4485e57309bbbc5b9489b496d5751b3ed783862a..a424981c69716f00eff413abd8b60e1240f2434d 100644 --- a/clang/test/Driver/clang-offload-bundler-zstd.c +++ b/clang/test/Driver/clang-offload-bundler-zstd.c @@ -22,19 +22,22 @@ // Check compression/decompression of offload bundle. // // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose 2>&1 | \ -// RUN: FileCheck -check-prefix=COMPRESS %s +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose >%t.1.txt 2>&1 // RUN: clang-offload-bundler -type=bc -list -input=%t.hip.bundle.bc | FileCheck -check-prefix=NOHOST %s // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose 2>&1 | \ -// RUN: FileCheck -check-prefix=DECOMPRESS %s +// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose >%t.2.txt 2>&1 +// RUN: cat %t.1.txt %t.2.txt | FileCheck %s // RUN: diff %t.tgt1 %t.res.tgt1 // RUN: diff %t.tgt2 %t.res.tgt2 // -// COMPRESS: Compression method used: zstd -// COMPRESS: Compression level: 3 -// DECOMPRESS: Decompression method: zstd -// DECOMPRESS: Hashes match: Yes +// CHECK: Compressed bundle format version: 2 +// CHECK: Total file size (including headers): [[SIZE:[0-9]*]] bytes +// CHECK: Compression method used: zstd +// CHECK: Compression level: 3 +// CHECK: Compressed bundle format version: 2 +// CHECK: Total file size (from header): [[SIZE]] bytes +// CHECK: Decompression method: zstd +// CHECK: Hashes match: Yes // NOHOST-NOT: host- // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906 diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index b209c911d1ca2b051350b998f4d0e6fe5645bf3a..7d061410a229f035b50a00f6147d3f200f096b4c 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -456,9 +456,9 @@ // RUN: %clang -### -target x86_64 -c -g %s 2>&1 | FileCheck --check-prefix=FULL_TEMP_NAMES --implicit-check-not=debug-forward-template-params %s // FULL_TEMP_NAMES-NOT: -gsimple-template-names -//// Test -g[no-]template-alias (enabled by default with SCE debugger tuning and DWARFv5). +//// Test -g[no-]template-alias (enabled by default with SCE debugger tuning and DWARF version >= 4). // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS -// RUN: %clang -### -target x86_64 -c -gdwarf-4 -gsce %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS +// RUN: %clang -### -target x86_64 -c -gdwarf-3 -gsce %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce -gtemplate-alias %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce -gno-template-alias %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gtemplate-alias %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS diff --git a/clang/test/Driver/integrated-as.c b/clang/test/Driver/integrated-as.c index d7658fdfd63374c241f3020f51a69cfcd47c6160..e78fde873cf47f3d535c2b9d7faadefc008991f6 100644 --- a/clang/test/Driver/integrated-as.c +++ b/clang/test/Driver/integrated-as.c @@ -1,10 +1,16 @@ // XFAIL: target={{.*}}-aix{{.*}} -// RUN: %clang -### -c -save-temps -integrated-as %s 2>&1 | FileCheck %s +// RUN: %clang -### -c -save-temps -integrated-as --target=x86_64 %s 2>&1 | FileCheck %s // CHECK: cc1as // CHECK: -mrelax-all +// RISC-V does not enable -mrelax-all +// RUN: %clang -### -c -save-temps -integrated-as --target=riscv64 %s 2>&1 | FileCheck %s -check-prefix=RISCV-RELAX + +// RISCV-RELAX: cc1as +// RISCV-RELAX-NOT: -mrelax-all + // RUN: %clang -### -fintegrated-as -c -save-temps %s 2>&1 | FileCheck %s -check-prefix FIAS // FIAS: cc1as diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index 5e1db5ba1ed3e96ddf939c9063c7cc98a11031d1..cfe293cd4667ff24c224a73353bfca8923beb2b7 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -37,6 +37,8 @@ // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mstrict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-UNALIGNED-ACCESS +// RUN: touch %t.o +// RUN: %clang --target=riscv32-unknown-elf -### %t.o -mno-strict-align -mstrict-align // FAST-UNALIGNED-ACCESS: "-target-feature" "+unaligned-scalar-mem" "-target-feature" "+unaligned-vector-mem" // NO-FAST-UNALIGNED-ACCESS: "-target-feature" "-unaligned-scalar-mem" "-target-feature" "-unaligned-vector-mem" diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index f5657e47626e1dc90dab11e76077c50e9538024d..7289d09697b4d09611c5a5c729e8c1390e2f58ff 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -802,10 +802,24 @@ // RUN: --target=i686-pc-windows \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CFI-STATS-WIN32 %s +// RUN: not %clang -fsanitize=cfi -fsanitize-stats -### %s 2>&1 \ +// RUN: --target=i686-pc-windows \ +// RUN: -fno-rtlib-defaultlib \ +// RUN: -frtlib-defaultlib \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-CFI-STATS-WIN32 %s // CHECK-CFI-STATS-WIN32: "--dependent-lib=clang_rt.stats_client{{(-i386)?}}.lib" // CHECK-CFI-STATS-WIN32: "--dependent-lib=clang_rt.stats{{(-i386)?}}.lib" // CHECK-CFI-STATS-WIN32: "--linker-option=/include:___sanitizer_stats_register" +// RUN: not %clang -fsanitize=cfi -fsanitize-stats -### %s 2>&1 \ +// RUN: --target=i686-pc-windows \ +// RUN: -fno-rtlib-defaultlib \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-CFI-STATS-WIN32-NODEF %s +// CHECK-CFI-STATS-WIN32-NODEF-NOT: "--dependent-lib=clang_rt.stats_client{{(-i386)?}}.lib" +// CHECK-CFI-STATS-WIN32-NODEF-NOT: "--dependent-lib=clang_rt.stats{{(-i386)?}}.lib" + // RUN: %clang -### %s 2>&1 \ // RUN: --target=arm-linux-androideabi -fuse-ld=ld -fsanitize=safe-stack \ // RUN: --sysroot=%S/Inputs/basic_android_tree \ diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c index 12ac73f0d4295ab9395c9060b7b4a590685dab6d..237b2ffa55d7dc781972299c2403d397707508e5 100644 --- a/clang/test/ExtractAPI/availability.c +++ b/clang/test/ExtractAPI/availability.c @@ -1,446 +1,101 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing -triple arm64-apple-macosx \ +// RUN: -x c-header %s -o %t/output.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix A +void a(void) __attribute__((availability(macos, introduced=12.0))); +// A-LABEL: "!testLabel": "c:@F@a" +// A: "availability": [ +// A-NEXT: { +// A-NEXT: "domain": "macos", +// A-NEXT: "introduced": { +// A-NEXT: "major": 12, +// A-NEXT: "minor": 0, +// A-NEXT: "patch": 0 +// A-NEXT: } +// A-NEXT: } +// A-NEXT: ] -// CHECK-NOT: error: -// CHECK-NOT: warning: +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix B +void b(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=20.0))); +// B-LABEL: "!testLabel": "c:@F@b" +// B: "availability": [ +// B-NEXT: { +// B-NEXT: "deprecated": { +// B-NEXT: "major": 12, +// B-NEXT: "minor": 0, +// B-NEXT: "patch": 0 +// B-NEXT: }, +// B-NEXT: "domain": "macos", +// B-NEXT: "introduced": { +// B-NEXT: "major": 11, +// B-NEXT: "minor": 0, +// B-NEXT: "patch": 0 +// B-NEXT: }, +// B-NEXT: "obsoleted": { +// B-NEXT: "major": 20, +// B-NEXT: "minor": 0, +// B-NEXT: "patch": 0 +// B-NEXT: } +// B-NEXT: } +// B-NEXT: ] -//--- input.h -void a(void); +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix E +void c(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=20.0))) __attribute__((availability(ios, introduced=13.0))); +// C-LABEL: "!testLabel": "c:@F@c" +// C: "availability": [ +// C-NEXT: { +// C-NEXT: "deprecated": { +// C-NEXT: "major": 12, +// C-NEXT: "minor": 0, +// C-NEXT: "patch": 0 +// C-NEXT: }, +// C-NEXT: "domain": "macos", +// C-NEXT: "introduced": { +// C-NEXT: "major": 11, +// C-NEXT: "minor": 0, +// C-NEXT: "patch": 0 +// C-NEXT: }, +// C-NEXT: "obsoleted": { +// C-NEXT: "major": 20, +// C-NEXT: "minor": 0, +// C-NEXT: "patch": 0 +// C-NEXT: } +// C-NEXT: } +// C-NEXT: ] -void b(void) __attribute__((availability(macos, introduced=12.0))); +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix D +void d(void) __attribute__((deprecated)) __attribute__((availability(macos, introduced=11.0))); +// D-LABEL: "!testLabel": "c:@F@d" +// D: "availability": [ +// D-NEXT: { +// D-NEXT: "domain": "*", +// D-NEXT: "isUnconditionallyDeprecated": true +// D-NEXT: }, +// D-NEXT: { +// D-NEXT: "domain": "macos", +// D-NEXT: "introduced": { +// D-NEXT: "major": 11, +// D-NEXT: "minor": 0, +// D-NEXT: "patch": 0 +// D-NEXT: } +// D-NEXT: } +// D-NEXT: ] -void c(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=20.0))); +// This symbol should be dropped as it's unconditionally unavailable +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix E +void e(void) __attribute__((unavailable)) __attribute__((availability(macos, introduced=11.0))); +// E-NOT: "!testLabel": "c:@F@e" -void d(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=20.0))) __attribute__((availability(ios, introduced=13.0))); +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix F +void f(void) __attribute__((availability(macos, unavailable))); +// F-LABEL: "!testLabel": "c:@F@f" +// F: "availability": [ +// F-NEXT: { +// F-NEXT: "domain": "macos", +// F-NEXT: "isUnconditionallyUnavailable": true +// F-NEXT: } +// F-NEXT: ] -void e(void) __attribute__((deprecated)) __attribute__((availability(macos, introduced=11.0))); +// expected-no-diagnostics -void f(void) __attribute__((unavailable)) __attribute__((availability(macos, introduced=11.0))); - -void d(void) __attribute__((availability(tvos, introduced=15.0))); - -void e(void) __attribute__((availability(tvos, unavailable))); - -///expected-no-diagnostics - -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "Availability", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "a" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@F@a" - }, - "kind": { - "displayName": "Function", - "identifier": "c.func" - }, - "location": { - "position": { - "character": 5, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "a" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "a" - } - ], - "title": "a" - }, - "pathComponents": [ - "a" - ] - }, - { - "accessLevel": "public", - "availability": [ - { - "domain": "macos", - "introduced": { - "major": 12, - "minor": 0, - "patch": 0 - } - } - ], - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "b" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@F@b" - }, - "kind": { - "displayName": "Function", - "identifier": "c.func" - }, - "location": { - "position": { - "character": 5, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "b" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "b" - } - ], - "title": "b" - }, - "pathComponents": [ - "b" - ] - }, - { - "accessLevel": "public", - "availability": [ - { - "deprecated": { - "major": 12, - "minor": 0, - "patch": 0 - }, - "domain": "macos", - "introduced": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "obsoleted": { - "major": 20, - "minor": 0, - "patch": 0 - } - } - ], - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "c" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@F@c" - }, - "kind": { - "displayName": "Function", - "identifier": "c.func" - }, - "location": { - "position": { - "character": 5, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "c" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "c" - } - ], - "title": "c" - }, - "pathComponents": [ - "c" - ] - }, - { - "accessLevel": "public", - "availability": [ - { - "deprecated": { - "major": 12, - "minor": 0, - "patch": 0 - }, - "domain": "macos", - "introduced": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "obsoleted": { - "major": 20, - "minor": 0, - "patch": 0 - } - } - ], - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "d" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@F@d" - }, - "kind": { - "displayName": "Function", - "identifier": "c.func" - }, - "location": { - "position": { - "character": 5, - "line": 6 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "d" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "d" - } - ], - "title": "d" - }, - "pathComponents": [ - "d" - ] - }, - { - "accessLevel": "public", - "availability": [ - { - "domain": "*", - "isUnconditionallyDeprecated": true - }, - { - "domain": "macos", - "introduced": { - "major": 11, - "minor": 0, - "patch": 0 - } - } - ], - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "e" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@F@e" - }, - "kind": { - "displayName": "Function", - "identifier": "c.func" - }, - "location": { - "position": { - "character": 5, - "line": 8 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "e" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "e" - } - ], - "title": "e" - }, - "pathComponents": [ - "e" - ] - } - ] -} diff --git a/clang/test/FixIt/format-darwin-enum-class.cpp b/clang/test/FixIt/format-darwin-enum-class.cpp index 5aa1a80d8614c20ebcd1d3b59cfa7c853142e64d..6d0bb80e982d7e2cf1644f212e23d85906f6be60 100644 --- a/clang/test/FixIt/format-darwin-enum-class.cpp +++ b/clang/test/FixIt/format-darwin-enum-class.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wformat %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wformat-pedantic %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -fdiagnostics-parseable-fixits -Wformat-pedantic %s 2>&1 | FileCheck %s extern "C" int printf(const char * restrict, ...); diff --git a/clang/test/FixIt/format.cpp b/clang/test/FixIt/format.cpp index 4e6573a4f9e54e3e96a685e167149fab0aa4327b..d663c0fb35e1385e34a2c9fce1a5af11971d80c6 100644 --- a/clang/test/FixIt/format.cpp +++ b/clang/test/FixIt/format.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat %s -// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-pedantic %s +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat-pedantic %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s -verify=okay +// okay-no-diagnostics extern "C" int printf(const char *, ...); #define LOG(...) printf(__VA_ARGS__) diff --git a/clang/test/Lexer/bitint-constants-compat.c b/clang/test/Lexer/bitint-constants-compat.c index 607ae88a6188bbb800d85580a24f884000fc8339..d8bff94ef88caa39ca4edec28bbc0bc5b71ca11f 100644 --- a/clang/test/Lexer/bitint-constants-compat.c +++ b/clang/test/Lexer/bitint-constants-compat.c @@ -1,14 +1,23 @@ // RUN: %clang_cc1 -std=c17 -fsyntax-only -verify=ext -Wno-unused %s // RUN: %clang_cc1 -std=c2x -fsyntax-only -verify=compat -Wpre-c2x-compat -Wno-unused %s -// RUN: %clang_cc1 -fsyntax-only -verify=cpp -Wno-unused -x c++ %s +// RUN: %clang_cc1 -fsyntax-only -verify=cpp -Wbit-int-extension -Wno-unused -x c++ %s #if 18446744073709551615uwb // ext-warning {{'_BitInt' suffix for literals is a C23 extension}} \ compat-warning {{'_BitInt' suffix for literals is incompatible with C standards before C23}} \ cpp-error {{invalid suffix 'uwb' on integer constant}} #endif +#if 18446744073709551615__uwb // ext-error {{invalid suffix '__uwb' on integer constant}} \ + compat-error {{invalid suffix '__uwb' on integer constant}} \ + cpp-warning {{'_BitInt' suffix for literals is a Clang extension}} +#endif + void func(void) { 18446744073709551615wb; // ext-warning {{'_BitInt' suffix for literals is a C23 extension}} \ compat-warning {{'_BitInt' suffix for literals is incompatible with C standards before C23}} \ cpp-error {{invalid suffix 'wb' on integer constant}} + + 18446744073709551615__wb; // ext-error {{invalid suffix '__wb' on integer constant}} \ + compat-error {{invalid suffix '__wb' on integer constant}} \ + cpp-warning {{'_BitInt' suffix for literals is a Clang extension}} } diff --git a/clang/test/Lexer/bitint-constants.cpp b/clang/test/Lexer/bitint-constants.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb6ac35467cd6716442d9c4d338514b08b1b2039 --- /dev/null +++ b/clang/test/Lexer/bitint-constants.cpp @@ -0,0 +1,178 @@ +// RUN: %clang_cc1 -triple aarch64-unknown-unknown -fsyntax-only -verify -Wno-unused %s + +// Test that the preprocessor behavior makes sense. +#if 1__wb != 1 +#error "wb suffix must be recognized by preprocessor" +#endif +#if 1__uwb != 1 +#error "uwb suffix must be recognized by preprocessor" +#endif +#if !(-1__wb < 0) +#error "wb suffix must be interpreted as signed" +#endif +#if !(-1__uwb > 0) +#error "uwb suffix must be interpreted as unsigned" +#endif + +#if 18446744073709551615__uwb != 18446744073709551615ULL +#error "expected the max value for uintmax_t to compare equal" +#endif + +// Test that the preprocessor gives appropriate diagnostics when the +// literal value is larger than what can be stored in a [u]intmax_t. +#if 18446744073709551616__wb != 0ULL // expected-error {{integer literal is too large to be represented in any integer type}} +#error "never expected to get here due to error" +#endif +#if 18446744073709551616__uwb != 0ULL // expected-error {{integer literal is too large to be represented in any integer type}} +#error "never expected to get here due to error" +#endif + +// Despite using a bit-precise integer, this is expected to overflow +// because all preprocessor arithmetic is done in [u]intmax_t, so this +// should result in the value 0. +#if 18446744073709551615__uwb + 1 != 0ULL +#error "expected modulo arithmetic with uintmax_t width" +#endif + +// Because this bit-precise integer is signed, it will also overflow, +// but Clang handles that by converting to uintmax_t instead of +// intmax_t. +#if 18446744073709551615__wb + 1 != 0LL // expected-warning {{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}} +#error "expected modulo arithmetic with uintmax_t width" +#endif + +// Test that just because the preprocessor can't figure out the bit +// width doesn't mean we can't form the constant, it just means we +// can't use the value in a preprocessor conditional. +unsigned _BitInt(65) Val = 18446744073709551616__uwb; +// UDL test to make sure underscore parsing is correct +unsigned operator ""_(const char *); + +void ValidSuffix(void) { + // Decimal literals. + 1__wb; + 1__WB; + -1__wb; + _Static_assert((int)1__wb == 1, "not 1?"); + _Static_assert((int)-1__wb == -1, "not -1?"); + + 1__uwb; + 1__uWB; + 1__Uwb; + 1__UWB; + 1u__wb; + 1__WBu; + 1U__WB; + _Static_assert((unsigned int)1__uwb == 1u, "not 1?"); + + 1'2__wb; + 1'2__uwb; + _Static_assert((int)1'2__wb == 12, "not 12?"); + _Static_assert((unsigned int)1'2__uwb == 12u, "not 12?"); + + // Hexadecimal literals. + 0x1__wb; + 0x1__uwb; + 0x0'1'2'3__wb; + 0xA'B'c'd__uwb; + _Static_assert((int)0x0'1'2'3__wb == 0x0123, "not 0x0123"); + _Static_assert((unsigned int)0xA'B'c'd__uwb == 0xABCDu, "not 0xABCD"); + + // Binary literals. + 0b1__wb; + 0b1__uwb; + 0b1'0'1'0'0'1__wb; + 0b0'1'0'1'1'0__uwb; + _Static_assert((int)0b1__wb == 1, "not 1?"); + _Static_assert((unsigned int)0b1__uwb == 1u, "not 1?"); + + // Octal literals. + 01__wb; + 01__uwb; + 0'6'0__wb; + 0'0'1__uwb; + 0__wbu; + 0__WBu; + 0U__wb; + 0U__WB; + 0__wb; + _Static_assert((int)0__wb == 0, "not 0?"); + _Static_assert((unsigned int)0__wbu == 0u, "not 0?"); + + // Imaginary or Complex. These are allowed because _Complex can work with any + // integer type, and that includes _BitInt. + 1__wbi; + 1i__wb; + 1__wbj; + + //UDL test as single underscore + unsigned i = 1.0_; +} + +void InvalidSuffix(void) { + // Can't mix the case of wb or WB, and can't rearrange the letters. + 0__wB; // expected-error {{invalid suffix '__wB' on integer constant}} + 0__Wb; // expected-error {{invalid suffix '__Wb' on integer constant}} + 0__bw; // expected-error {{invalid suffix '__bw' on integer constant}} + 0__BW; // expected-error {{invalid suffix '__BW' on integer constant}} + + // Trailing digit separators should still diagnose. + 1'2'__wb; // expected-error {{digit separator cannot appear at end of digit sequence}} + 1'2'__uwb; // expected-error {{digit separator cannot appear at end of digit sequence}} + + // Long. + 1l__wb; // expected-error {{invalid suffix}} + 1__wbl; // expected-error {{invalid suffix}} + 1l__uwb; // expected-error {{invalid suffix}} + 1__l; // expected-error {{invalid suffix}} + 1ul__wb; // expected-error {{invalid suffix}} + + // Long long. + 1ll__wb; // expected-error {{invalid suffix}} + 1__uwbll; // expected-error {{invalid suffix}} + + // Floating point. + 0.1__wb; // expected-error {{invalid suffix}} + 0.1f__wb; // expected-error {{invalid suffix}} + + // Repetitive suffix. + 1__wb__wb; // expected-error {{invalid suffix}} + 1__uwbuwb; // expected-error {{invalid suffix}} + 1__wbuwb; // expected-error {{invalid suffix}} + 1__uwbwb; // expected-error {{invalid suffix}} + + // Missing or extra characters in suffix. + 1__; // expected-error {{invalid suffix}} + 1__u; // expected-error {{invalid suffix}} + 1___; // expected-error {{invalid suffix}} + 1___WB; // expected-error {{invalid suffix}} + 1__wb__; // expected-error {{invalid suffix}} + 1__w; // expected-error {{invalid suffix}} + 1__b; // expected-error {{invalid suffix}} +} + +void ValidSuffixInvalidValue(void) { + // This is a valid suffix, but the value is larger than one that fits within + // the width of BITINT_MAXWIDTH. When this value changes in the future, the + // test cases should pick a new value that can't be represented by a _BitInt, + // but also add a test case that a 129-bit literal still behaves as-expected. + _Static_assert(__BITINT_MAXWIDTH__ <= 128, + "Need to pick a bigger constant for the test case below."); + 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1__wb; // expected-error {{integer literal is too large to be represented in any signed integer type}} + 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1__uwb; // expected-error {{integer literal is too large to be represented in any integer type}} +} + +void TestTypes(void) { + // 2 value bits, one sign bit + _Static_assert(__is_same(decltype(3__wb), _BitInt(3))); + // 2 value bits, one sign bit + _Static_assert(__is_same(decltype(-3__wb), _BitInt(3))); + // 2 value bits, no sign bit + _Static_assert(__is_same(decltype(3__uwb), unsigned _BitInt(2))); + // 4 value bits, one sign bit + _Static_assert(__is_same(decltype(0xF__wb), _BitInt(5))); + // 4 value bits, one sign bit + _Static_assert(__is_same(decltype(-0xF__wb), _BitInt(5))); + // 4 value bits, no sign bit + _Static_assert(__is_same(decltype(0xF__uwb), unsigned _BitInt(4))); +} diff --git a/clang/test/Modules/add-remove-irrelevant-module-map.m b/clang/test/Modules/add-remove-irrelevant-module-map.m deleted file mode 100644 index 7e3e58037e6f21100c15fa294b72b58d7c08371b..0000000000000000000000000000000000000000 --- a/clang/test/Modules/add-remove-irrelevant-module-map.m +++ /dev/null @@ -1,32 +0,0 @@ -// RUN: rm -rf %t && mkdir %t -// RUN: split-file %s %t - -//--- a/module.modulemap -module a {} - -//--- b/module.modulemap -module b {} - -//--- c/module.modulemap -module c {} - -//--- module.modulemap -module m { header "m.h" } -//--- m.h -@import c; - -//--- test-simple.m -// expected-no-diagnostics -@import m; - -// Build modules with the non-affecting "a/module.modulemap". -// RUN: %clang_cc1 -I %t/a -I %t/b -I %t/c -I %t -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -fdisable-module-hash %t/test-simple.m -verify -// RUN: mv %t/cache %t/cache-with - -// Build modules without the non-affecting "a/module.modulemap". -// RUN: rm -rf %t/a/module.modulemap -// RUN: %clang_cc1 -I %t/a -I %t/b -I %t/c -I %t -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -fdisable-module-hash %t/test-simple.m -verify -// RUN: mv %t/cache %t/cache-without - -// Check that the PCM files are bit-for-bit identical. -// RUN: diff %t/cache-with/m.pcm %t/cache-without/m.pcm diff --git a/clang/test/Modules/prune-non-affecting-module-map-files.m b/clang/test/Modules/prune-non-affecting-module-map-files.m new file mode 100644 index 0000000000000000000000000000000000000000..ba2b3a306eaf460c85fc3594e90943b13d33f967 --- /dev/null +++ b/clang/test/Modules/prune-non-affecting-module-map-files.m @@ -0,0 +1,62 @@ +// Check that the presence of non-affecting module map files does not affect the +// contents of PCM files. + +// RUN: rm -rf %t && mkdir %t +// RUN: split-file %s %t + +//--- a/module.modulemap +module a {} + +//--- b/module.modulemap +module b {} + +//--- c/module.modulemap +module c { header "c.h" } +//--- c/c.h +@import b; + +//--- tu.m +@import c; + +//--- explicit-mms-common-args.rsp +-fmodule-map-file=b/module.modulemap -fmodule-map-file=c/module.modulemap -fmodules -fmodules-cache-path=cache -fdisable-module-hash -fsyntax-only tu.m +//--- implicit-search-args.rsp +-I a -I b -I c -fimplicit-module-maps -fmodules -fmodules-cache-path=cache -fdisable-module-hash -fsyntax-only tu.m +//--- implicit-search-args.rsp-end + +// Test with explicit module map files. +// +// RUN: %clang_cc1 -working-directory %t @%t/explicit-mms-common-args.rsp +// RUN: mv %t/cache %t/cache-explicit-no-a-prune +// RUN: %clang_cc1 -working-directory %t @%t/explicit-mms-common-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-explicit-no-a-keep +// +// RUN: %clang_cc1 -working-directory %t -fmodule-map-file=a/module.modulemap @%t/explicit-mms-common-args.rsp +// RUN: mv %t/cache %t/cache-explicit-a-prune +// RUN: %clang_cc1 -working-directory %t -fmodule-map-file=a/module.modulemap @%t/explicit-mms-common-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-explicit-a-keep +// +// RUN: diff %t/cache-explicit-no-a-prune/c.pcm %t/cache-explicit-a-prune/c.pcm +// RUN: not diff %t/cache-explicit-no-a-keep/c.pcm %t/cache-explicit-a-keep/c.pcm + +// Test with implicit module map search. +// +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp +// RUN: mv %t/cache %t/cache-implicit-no-a-prune +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-implicit-no-a-keep +// +// FIXME: Instead of removing "a/module.modulemap" from the file system, we +// could drop the "-I a" search path argument in combination with the +// "-fmodules-skip-header-search-paths" flag. Unfortunately, that flag +// does not prevent serialization of the search path usage bit vector, +// making the files differ anyways. +// RUN: rm %t/a/module.modulemap +// +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp +// RUN: mv %t/cache %t/cache-implicit-a-prune +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-implicit-a-keep +// +// RUN: diff %t/cache-implicit-no-a-prune/c.pcm %t/cache-implicit-a-prune/c.pcm +// RUN: not diff %t/cache-implicit-no-a-keep/c.pcm %t/cache-implicit-a-keep/c.pcm diff --git a/clang/test/Parser/cxx2a-constrained-template-param.cpp b/clang/test/Parser/cxx2a-constrained-template-param.cpp index 6f14b66419c4981a997a85b31493621fcd0f0128..d27f0f8db9b885aab1b975734f367a6b5474f89e 100644 --- a/clang/test/Parser/cxx2a-constrained-template-param.cpp +++ b/clang/test/Parser/cxx2a-constrained-template-param.cpp @@ -49,4 +49,22 @@ namespace temp template // expected-error{{use of class template 'test1' requires template arguments}} // expected-error@-1 2{{concept named in type constraint is not a type concept}} using A = TT; // expected-error{{expected ';' after alias declaration}} -} \ No newline at end of file +} + +namespace PR67235 { + +template +concept C = true; + +template +struct S {}; + +// Don't destroy annotation 'C' at the end of the lambda; else we'll run into a +// use-after-free bug while constructing the type constraint 'C' on 'Default'. +template +void func() {} + +template > +void func2() {} + +} diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index ddf40f71701eda4522e9df5032352d165e956b7d..799f22b8c120e599c2fdcf775934a2928ec5b264 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -911,16 +911,12 @@ void IntExprParsing() { #pragma acc parallel num_gangs(invalid) {} - // expected-error@+2{{expected ')'}} - // expected-note@+1{{to match this '('}} #pragma acc parallel num_gangs(5, 4) {} - // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}} #pragma acc parallel num_gangs(5) {} - // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}} #pragma acc parallel num_gangs(returns_int()) {} diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c index 55c97c73e8b6952a634bdd0095afc741bfbeaa64..6a1feeb9bf53976325eda4e393c738a392c103b9 100644 --- a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c +++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ -// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s +// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -Waarch64-sme-attributes -fsyntax-only -verify %s // REQUIRES: aarch64-registered-target @@ -33,6 +33,7 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); @@ -48,6 +49,7 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); @@ -68,6 +70,7 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_ return svadd_n_f64_m(pg, a, b); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) { // expected-no-warning return svadd_n_f64_m(pg, a, b); @@ -83,6 +86,7 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming { return svmul_lane_s16(op1, op2, 0); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) { // expected-no-warning return svmul_lane_s16(op1, op2, 0); diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index bfc8768c3f36e1c0c07cf1b1362275870aca2323..12de16509ccb8d276282c14263614d83e29dc6b3 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify=expected-cpp -x c++ %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s // Valid attributes @@ -496,3 +496,135 @@ void fmv_caller() { just_fine(); incompatible_locally_streaming(); } + +void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { } + +__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; } + +void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { } + +__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible { __SVInt8_t r; return r; } + +void sme_no_streaming_with_vl_arg(__SVInt8_t a) { } + +__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; } + +// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +__arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { } + +// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +__arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; } + +void sme_no_streaming_calling_streaming_with_vl_args() { + __SVInt8_t a; + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_streaming_with_vl_arg(a); +} + +void sme_no_streaming_calling_streaming_with_return_vl() { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { + __SVInt8_t a; + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_no_streaming_with_vl_arg(a); +} + +void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sc(arg); +} + +__SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + return s(); +} + +void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_streaming_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_no_streaming_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_streaming_calling_streaming(__SVInt8_t arg, void (*s)( __SVInt8_t arg) __arm_streaming) __arm_streaming { + s(arg); +} + +__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*s)(void) __arm_streaming) __arm_streaming { + return s(); +} + +void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming { + sme_streaming_with_vl_arg(a); +} + +void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming { + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm_streaming { + sme_streaming_compatible_with_vl_arg(a); +} + +void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} + +void sme_no_streaming_calling_streaming_compatible_with_vl_args() { + __SVInt8_t a; + sme_streaming_compatible_with_vl_arg(a); +} + +void sme_no_streaming_calling_streaming_compatible_with_return_vl() { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} + +void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() { + __SVInt8_t a; + sme_no_streaming_with_vl_arg(a); +} + +void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() { + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + sme_streaming_compatible_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} diff --git a/clang/test/Sema/bitint-bitfield-promote.c b/clang/test/Sema/bitint-bitfield-promote.c new file mode 100644 index 0000000000000000000000000000000000000000..e82e94975cfd4ac36825ca99f865ac6fc8b01e87 --- /dev/null +++ b/clang/test/Sema/bitint-bitfield-promote.c @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s + +// GH87641 noticed that integer promotion of a bit-field of bit-precise integer +// type was promoting to int rather than the type of the bit-field. +struct S { + unsigned _BitInt(7) x : 2; + unsigned _BitInt(2) y : 2; + unsigned _BitInt(72) z : 28; + _BitInt(31) a : 12; + _BitInt(33) b : 33; +}; + +// We don't have to worry about promotion cases where the bit-precise type is +// smaller than the width of the bit-field; that can't happen. +struct T { + unsigned _BitInt(28) oh_no : 72; // expected-error {{width of bit-field 'oh_no' (72 bits) exceeds the width of its type (28 bits)}} +}; + +static_assert( + _Generic(+(struct S){}.x, + int : 0, + unsigned _BitInt(7) : 1, + unsigned _BitInt(2) : 2 + ) == 1); + +static_assert( + _Generic(+(struct S){}.y, + int : 0, + unsigned _BitInt(7) : 1, + unsigned _BitInt(2) : 2 + ) == 2); + +static_assert( + _Generic(+(struct S){}.z, + int : 0, + unsigned _BitInt(72) : 1, + unsigned _BitInt(28) : 2 + ) == 1); + +static_assert( + _Generic(+(struct S){}.a, + int : 0, + _BitInt(31) : 1, + _BitInt(12) : 2, + unsigned _BitInt(31) : 3 + ) == 1); + +static_assert( + _Generic(+(struct S){}.b, + int : 0, + long long : 1, + _BitInt(33) : 2, + unsigned _BitInt(33) : 3 + ) == 2); diff --git a/clang/test/Sema/ppc-attr-target-inline.c b/clang/test/Sema/ppc-attr-target-inline.c index 07ed006822658437bef3055d32e45cac807b914e..ad198b842bb0329a474de8ce5cb0beebeff05498 100644 --- a/clang/test/Sema/ppc-attr-target-inline.c +++ b/clang/test/Sema/ppc-attr-target-inline.c @@ -1,5 +1,5 @@ // REQUIRES: powerpc-registered-target -// RUN: %clang_cc1 -triple powerpc64le -target-feature +htm -fsyntax-only -emit-llvm %s -verify +// RUN: %clang_cc1 -triple powerpc64le -target-feature +htm -fsyntax-only -emit-llvm-only %s -verify __attribute__((always_inline)) int test1(int *x) { diff --git a/clang/test/Sema/unroll-template-value-crash.cpp b/clang/test/Sema/unroll-template-value-crash.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8953c4845c265fae4aeda2bdb0f5c8d77f43ece --- /dev/null +++ b/clang/test/Sema/unroll-template-value-crash.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -x c++ -verify %s +// expected-no-diagnostics + +template void foo() { + #pragma unroll Unroll + for (int i = 0; i < Unroll; ++i); + + #pragma GCC unroll Unroll + for (int i = 0; i < Unroll; ++i); +} diff --git a/clang/test/SemaCXX/PR41441.cpp b/clang/test/SemaCXX/PR41441.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f60b6e209207a8fe787b1912c6aaa2f7ed19013 --- /dev/null +++ b/clang/test/SemaCXX/PR41441.cpp @@ -0,0 +1,32 @@ +// RUN: %clang --target=x86_64-pc-linux -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s + +namespace std { + using size_t = decltype(sizeof(int)); +}; +void* operator new[](std::size_t, void*) noexcept; + +// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 8, i1 false) +// CHECK: call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false) +template +void f() +{ + typedef TYPE TArray[8]; + + TArray x; + new(&x) TArray(); +} + +template +void f1() { + int (*x)[1] = new int[1][1]; +} +template void f1(); +void f2() { + int (*x)[1] = new int[1][1]; +} + +int main() +{ + f(); + f(); +} diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 6f04264a655ad5376081203ee14e408ed25c13d7..508a3a5da76a915ff6f0726b51eb8cbf5fdf4783 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -289,3 +289,21 @@ using String = Array; // Verify no crash on constructing the aggregate deduction guides. String s("hello"); } // namespace test21 + +// GH89013 +namespace test22 { +class Base {}; +template +class Derived final : public Base {}; + +template +requires __is_base_of(Base, D) +struct Foo { + explicit Foo(D) {} +}; + +template +using AFoo = Foo>; + +AFoo a(Derived{}); +} // namespace test22 diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index 478da092471affa037b12dcf0d6441281e2d4e3e..8676970de14f61ed2a45df2d3e71f559ca86bbe7 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -std=c++23 -x c++ %s -verify // RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected +// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected -fexperimental-new-constant-interpreter struct A{}; struct B{ explicit operator bool() { return true; } }; diff --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp index e13635383b6ca6b909b23cf8d8160568e1f1ec4e..606715e6aacffdbbd5fadcd5525ceacf4e6dc278 100644 --- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp +++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp @@ -154,3 +154,9 @@ void f() { } } + +namespace GH88929 { + bool b = a...[0]; // expected-error {{use of undeclared identifier 'a'}} + using E = P...[0]; // expected-error {{unknown type name 'P'}} \ + // expected-error {{expected ';' after alias declaration}} +} diff --git a/clang/test/SemaCXX/format-strings.cpp b/clang/test/SemaCXX/format-strings.cpp index f554e905d6455bde4aed34c06d8dba7f1924b041..48cf23999a94f7ba79d4fe527dbf0db3566db559 100644 --- a/clang/test/SemaCXX/format-strings.cpp +++ b/clang/test/SemaCXX/format-strings.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -Wformat-pedantic -fblocks %s // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -Wformat-pedantic -fblocks -std=c++11 %s #include diff --git a/clang/test/SemaCXX/static-assert-cxx26.cpp b/clang/test/SemaCXX/static-assert-cxx26.cpp index f4ede74f9214a44bb7fb68962871980cdb5f1830..7d896d8b365b740e3dec35971f7cb47eabccca6b 100644 --- a/clang/test/SemaCXX/static-assert-cxx26.cpp +++ b/clang/test/SemaCXX/static-assert-cxx26.cpp @@ -341,3 +341,77 @@ struct Callable { } data; }; static_assert(false, Callable{}); // expected-error {{static assertion failed: hello}} + +namespace GH89407 { +struct A { + constexpr __SIZE_TYPE__ size() const { return -1; } + constexpr const char* data() const { return ""; } +}; + +struct B { + constexpr long long size() const { return 18446744073709551615U; } + constexpr const char* data() const { return ""; } +}; + +struct C { + constexpr __int128 size() const { return -1; } + constexpr const char* data() const { return ""; } +}; + +struct D { + constexpr unsigned __int128 size() const { return -1; } + constexpr const char* data() const { return ""; } +}; + +struct E { + constexpr __SIZE_TYPE__ size() const { return 18446744073709551615U; } + constexpr const char* data() const { return ""; } +}; + +static_assert(true, A{}); // expected-error {{the message in this static assertion is not a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, B{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in this static assertion is not a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, C{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in this static assertion is not a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, D{}); // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in this static assertion is not a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, E{}); // expected-error {{the message in this static assertion is not a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} + +static_assert( + false, // expected-error {{static assertion failed}} + A{} // expected-error {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + B{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + C{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + D{} // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + E{} // expected-error {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); +} diff --git a/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl index 862b94652073122e6249d7a60e2df9b58c838cab..7bb5308c5d5ba7bfa8066b6430d20a01cf7defd4 100644 --- a/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected bool test_too_few_arg() { return __builtin_hlsl_elementwise_any(); diff --git a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl index 4c0e5315ce532e14360d5ca899a6e559d899e640..f669098ef515d8d4e97131b6af0f5395188b25c4 100644 --- a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float2 test_no_second_arg(float2 p0) { return __builtin_hlsl_elementwise_clamp(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl index ba7ffc20484ae01b511f370e1fa25e254606527a..095f3c12ba8731d047bf2c5dd16edfef5cea9494 100644 --- a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_no_second_arg(float2 p0) { return __builtin_hlsl_dot(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl index e2e79abb74a32d213cacef1a53ebde3004f2a917..321fc915ec01fcbde4433f7c2143cf662a178575 100644 --- a/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp2 float test_too_few_arg() { return TEST_FUNC(); // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} diff --git a/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl index f82b5942fd46b6112f153e7538dd4d9cd362b7d6..f3cfbcf29d69c2b9bac4bd68d901c6202ae48b77 100644 --- a/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_hlsl_elementwise_frac(); diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl index 98c02c38675f4e13989e3fef87bf6168641abe68..ef0928f8fef0d6069595b40f44b610d01c5b9dc6 100644 --- a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl @@ -1,15 +1,15 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_ceil -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_cos -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp2 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_floor -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log2 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_ceil +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_cos +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_floor +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc double2 test_double_builtin(double2 p0) { return TEST_FUNC(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl index 7ddfd56638273bdf0aecf1fef9dd5bf4cd4ab036..e2f03812705fd51ffe5bad94866647487b02c964 100644 --- a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected bool test_too_few_arg() { return __builtin_hlsl_elementwise_isinf(); diff --git a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl index 83751f68357edf36c3135107353c07061fd8fede..d23357239b7e8ab500ae78e8444ad02a2b555d5c 100644 --- a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float2 test_no_second_arg(float2 p0) { return __builtin_hlsl_lerp(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl index 97ce931bf1b5b591de99c91609829462e8a27ea2..636910b7ac8abc3381639114ecd0738eec3b08d6 100644 --- a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float2 test_no_second_arg(float2 p0) { return __builtin_hlsl_mad(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl index 949028aacf24b610c7932f75f8a544190395d9f0..5a2c9a3ef62ff56fcb39b9cb93cd9de2594b3316 100644 --- a/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify double2 test_double_builtin(double2 p0, double2 p1) { return __builtin_elementwise_pow(p0,p1); diff --git a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl index fa6fd813f19e64e6b13b5eda1717385d101bce96..6bc5b9bed3047c575ca898895bf95e09ef1f3617 100644 --- a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_hlsl_elementwise_rcp(); diff --git a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl index 6e66db6d1cca9e2f110980cbd88ba47d3d375e14..49cd895d98c52d242271d6b41a259b48f185eb4b 100644 --- a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify double2 test_int_builtin(double2 p0) { diff --git a/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl index fed4573063acb531934b7fff6d17aab6f744bf38..bede89015298b689d3f18348369abccf234e0c8a 100644 --- a/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_elementwise_round(); diff --git a/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl index c027a698c5e58fd576f19e0cc6604519110a9eca..e9a295172c7f8e3929793b610babfae559fe30a0 100644 --- a/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_hlsl_elementwise_rsqrt(); diff --git a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp index 889025c26818d844e55fff15de6f6574a2fa4268..5a4c9f05ee089e56fce680dd0aff6d692a7967d3 100644 --- a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp +++ b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp @@ -88,6 +88,34 @@ void NormalUses() { // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_gangs(some_int(), some_long(), some_short()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: CallExpr{{.*}}'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'int (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'int ()' lvalue Function{{.*}} 'some_int' 'int ()' + // CHECK-NEXT: CallExpr{{.*}}'long' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'long (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'long ()' lvalue Function{{.*}} 'some_long' 'long ()' + // CHECK-NEXT: CallExpr{{.*}}'short' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'short (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'short ()' lvalue Function{{.*}} 'some_short' 'short ()' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels num_gangs(some_int()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: CallExpr{{.*}}'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'int (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'int ()' lvalue Function{{.*}} 'some_int' 'int ()' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt } template @@ -187,6 +215,31 @@ void TemplUses(T t, U u) { // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: CompoundStmt +#pragma acc kernels num_gangs(u) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_gangs(u, U::value) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}EndMarker + int EndMarker; + // Check the instantiated versions of the above. // CHECK-NEXT: FunctionDecl{{.*}} used TemplUses 'void (CorrectConvert, HasInt)' implicit_instantiation // CHECK-NEXT: TemplateArgument type 'CorrectConvert' @@ -288,6 +341,32 @@ void TemplUses(T t, U u) { // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'char' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'char' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator char + // CHECK-NEXT: DeclRefExpr{{.*}} 'HasInt' lvalue ParmVar + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'char' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'char' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator char + // CHECK-NEXT: DeclRefExpr{{.*}} 'HasInt' lvalue ParmVar + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const int' lvalue Var{{.*}} 'value' 'const int' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'HasInt' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}EndMarker } struct HasInt { diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..cdc6847b47f9482c78174f624c447bb2e7f81ebc --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +short getS(); +void Test() { +#pragma acc kernels num_gangs(1) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1) + while(1); + +#pragma acc parallel num_gangs(1) + while(1); + + // expected-error@+2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'kernels' directive}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels num_gangs(1) num_gangs(2) + while(1); + + // expected-error@+2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'parallel' directive}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel num_gangs(1) num_gangs(2) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'kernels' directive expects maximum of 1, 2 were provided}} +#pragma acc kernels num_gangs(1, getS()) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1, getS()) + while(1); +#pragma acc parallel num_gangs(1, getS()) + while(1); + + struct NotConvertible{} NC; + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(NC) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(1, NC) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(NC, 1) + while(1); + +#pragma acc parallel num_gangs(getS(), 1, getS()) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'parallel' directive expects maximum of 3, 4 were provided}} +#pragma acc parallel num_gangs(getS(), 1, getS(), 1) + while(1); +} diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec3df87a065572f71518fccb8384eb3e36043240 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp @@ -0,0 +1,160 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NotConvertible{} NC; +struct Incomplete *SomeIncomplete; // #INCOMPLETE +enum E{} SomeE; +enum class E2{} SomeE2; + +struct CorrectConvert { + operator int(); +} Convert; + +struct ExplicitConvertOnly { + explicit operator int() const; // #EXPL_CONV +} Explicit; + +struct AmbiguousConvert{ + operator int(); // #AMBIG_INT + operator short(); // #AMBIG_SHORT + operator float(); +} Ambiguous; + +short some_short(); +int some_int(); +long some_long(); + +void Test() { +#pragma acc kernels num_gangs(1) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1) + while(1); + +#pragma acc parallel num_gangs(1) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(some_short(), some_int(), some_long()) + while(1); + +#pragma acc parallel num_gangs(some_short(), some_int(), some_long()) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(some_short(), some_int(), some_long(), SomeE) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'parallel' directive expects maximum of 3, 4 were provided}} +#pragma acc parallel num_gangs(some_short(), some_int(), some_long(), SomeE) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'kernels' directive expects maximum of 1, 2 were provided}} +#pragma acc kernels num_gangs(1, 2) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1, 2) + while(1); + +#pragma acc parallel num_gangs(1, 2) + while(1); + + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc parallel num_gangs(Ambiguous) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(NC, SomeE) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(SomeE, NC) + while(1); + + // expected-error@+3{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(Explicit, NC) + while(1); + + // expected-error@+4{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+2{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(Explicit, NC) + while(1); + + // expected-error@+6{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+4{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc parallel num_gangs(Explicit, NC, Ambiguous) + while(1); + + // expected-error@+7{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+5{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+4{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(Explicit, NC, Ambiguous) + while(1); + // TODO +} + +struct HasInt { + using IntTy = int; + using ShortTy = short; + static constexpr int value = 1; + static constexpr AmbiguousConvert ACValue; + static constexpr ExplicitConvertOnly EXValue; + + operator char(); +}; + +template +void TestInst() { + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(HasInt::Invalid) + while(1); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc parallel num_gangs(T::Invalid) + while(1); + + // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel num_gangs(1, HasInt::Invalid) + while(1); + + // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel num_gangs(T::Invalid, 1) + while(1); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1, HasInt::Invalid) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(T::Invalid, 1) + while(1); + +#pragma acc parallel num_gangs(T::value, typename T::IntTy{}) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(T::value, typename T::IntTy{}) + while(1); +} + +void Inst() { + TestInst(); // #INST +} diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 58f08aa1eed65029489f2f8a5c05b1f5e6350c84..ff5e39216762faf291206242cc8467b1a43b3404 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -260,3 +260,31 @@ AG ag = {1}; // CHECK: |-TemplateArgument type 'int' // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' + +template +requires (sizeof(D) == 4) +struct Foo { + Foo(D); +}; + +template +using AFoo = Foo>; +// Verify that the require-clause from the Foo deduction guide is transformed. +// The D occurrence should be rewritten to G. +// +// CHECK-LABEL: Dumping +// CHECK: FunctionTemplateDecl {{.*}} implicit +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 U +// CHECK-NEXT: |-ParenExpr {{.*}} 'bool' +// CHECK-NEXT: | `-BinaryOperator {{.*}} 'bool' '==' +// CHECK-NEXT: | |-UnaryExprOrTypeTraitExpr {{.*}} 'G' +// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} +// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (G) -> Foo>' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} 'G' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (G) -> Foo>' implicit_instantiation +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +// CHECK-NEXT: `-ParmVarDecl {{.*}} 'G' + +AFoo aa(G{}); diff --git a/clang/test/SemaTemplate/instantiate-using-decl.cpp b/clang/test/SemaTemplate/instantiate-using-decl.cpp index 0bbb3ca9c88c8b5e1898a768ef57913edf6fb1df..28d83764385131d02ab735b9a447da77724ba76a 100644 --- a/clang/test/SemaTemplate/instantiate-using-decl.cpp +++ b/clang/test/SemaTemplate/instantiate-using-decl.cpp @@ -121,7 +121,7 @@ template struct Derived : Base { (void)&field; // expected-error@+1 {{call to non-static member function without an object argument}} (void)method; - // expected-error@+1 {{call to non-static member function without an object argument}} + // expected-error@+1 {{must explicitly qualify name of member function when taking its address}} (void)&method; // expected-error@+1 {{call to non-static member function without an object argument}} method(); diff --git a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp index dcab9bfaeabcb080e55111f289b6d3655cd64c2a..c49d2cb2422fabf776a1dbbb7807630a9c00b47f 100644 --- a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp +++ b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -1,7 +1,6 @@ -// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s -// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -Wno-unused-value -verify %s +// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -Wno-unused-value -verify %s -// expected-no-diagnostics class A { public: template A(U p) {} @@ -76,3 +75,453 @@ struct S { int f<0>(int); }; } + +namespace UsesThis { + template + struct A { + int x; + + static inline int y; + + template + static void f(); + + template + void g(); + + template + static auto h() -> A*; + + void i(); + + static void j(); + + template<> + void f() { + this->x; // expected-error {{invalid use of 'this' outside of a non-static member function}} + x; // expected-error {{invalid use of member 'x' in static member function}} + A::x; // expected-error {{invalid use of member 'x' in static member function}} + +x; // expected-error {{invalid use of member 'x' in static member function}} + +A::x; // expected-error {{invalid use of member 'x' in static member function}} + &x; // expected-error {{invalid use of member 'x' in static member function}} + &A::x; + this->y; // expected-error {{invalid use of 'this' outside of a non-static member function}} + y; + A::y; + +y; + +A::y; + &y; + &A::y; + f(); + f(); + g(); // expected-error {{call to non-static member function without an object argument}} + g(); // expected-error {{call to non-static member function without an object argument}} + i(); // expected-error {{call to non-static member function without an object argument}} + j(); + &i; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &j; + &A::i; + &A::j; + } + + template<> + void g() { + this->x; + x; + A::x; + +x; + +A::x; + &x; + &A::x; + this->y; + y; + A::y; + +y; + +A::y; + &y; + &A::y; + f(); + f(); + g(); + g(); + i(); + j(); + &i; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &j; + &A::i; + &A::j; + } + + template<> + auto h() -> decltype(this); // expected-error {{'this' cannot be used in a static member function declaration}} + }; + + template struct A; // expected-note 3{{in instantiation of}} + + template + struct Foo { + template + int bar(X x) { + return 0; + } + + template <> + int bar(int x) { + return bar(5.0); // ok + } + }; + + void call() { + Foo f; + f.bar(1); + } + + struct B { + int x0; + static inline int y0; + + int f0(int); + static int g0(int); + + int x2; + static inline int y2; + + int f2(int); + static int g2(int); + }; + + template + struct D : B { + int x1; + static inline int y1; + + int f1(int); + static int g1(int); + + using B::x2; + using B::y2; + using B::f2; + using B::g2; + + template + void non_static_spec(U); + + template + static void static_spec(U); + + template<> + void non_static_spec(int z) { + ++z; + ++x0; + ++x1; + ++x2; + ++y0; + ++y1; + ++y2; + + &z; + &x0; + &x1; + &x2; + &y0; + &y1; + &y2; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &f2; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + &g2; + + &B::x0; + &D::x1; + &B::x2; + &B::y0; + &D::y1; + &B::y2; + &B::f0; + &D::f1; + &B::f2; + &B::g0; + &D::g1; + &B::g2; + + f0(0); + f0(z); + f0(x0); + f0(x1); + f0(x2); + f0(y0); + f0(y1); + f0(y2); + g0(0); + g0(z); + g0(x0); + g0(x1); + g0(x2); + g0(y0); + g0(y1); + g0(y2); + + f1(0); + f1(z); + f1(x0); + f1(x1); + f1(x2); + f1(y0); + f1(y1); + f1(y2); + g1(0); + g1(z); + g1(x0); + g1(x1); + g1(x2); + g1(y0); + g1(y1); + g1(y2); + + f2(0); + f2(z); + f2(x0); + f2(x1); + f2(x2); + f2(y0); + f2(y1); + f2(y2); + g2(0); + g2(z); + g2(x0); + g2(x1); + g2(x2); + g2(y0); + g2(y1); + g2(y2); + } + + template<> + void static_spec(int z) { + ++z; + ++x0; // expected-error {{invalid use of member 'x0' in static member function}} + ++x1; // expected-error {{invalid use of member 'x1' in static member function}} + ++x2; // expected-error {{invalid use of member 'x2' in static member function}} + ++y0; + ++y1; + ++y2; + + &z; + &x0; // expected-error {{invalid use of member 'x0' in static member function}} + &x1; // expected-error {{invalid use of member 'x1' in static member function}} + &x2; // expected-error {{invalid use of member 'x2' in static member function}} + &y0; + &y1; + &y2; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &f2; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + &g2; + + &B::x0; + &D::x1; + &B::x2; + &B::y0; + &D::y1; + &B::y2; + &B::f0; + &D::f1; + &B::f2; + &B::g0; + &D::g1; + &B::g2; + + f0(0); // expected-error {{call to non-static member function without an object argument}} + f0(z); // expected-error {{call to non-static member function without an object argument}} + f0(x0); // expected-error {{call to non-static member function without an object argument}} + f0(x1); // expected-error {{call to non-static member function without an object argument}} + f0(x2); // expected-error {{call to non-static member function without an object argument}} + f0(y0); // expected-error {{call to non-static member function without an object argument}} + f0(y1); // expected-error {{call to non-static member function without an object argument}} + f0(y2); // expected-error {{call to non-static member function without an object argument}} + g0(0); + g0(z); + g0(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g0(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g0(x2); // expected-error {{invalid use of member 'x2' in static member function}} + g0(y0); + g0(y1); + g0(y2); + + f1(0); // expected-error {{call to non-static member function without an object argument}} + f1(z); // expected-error {{call to non-static member function without an object argument}} + f1(x0); // expected-error {{call to non-static member function without an object argument}} + f1(x1); // expected-error {{call to non-static member function without an object argument}} + f1(x2); // expected-error {{call to non-static member function without an object argument}} + f1(y0); // expected-error {{call to non-static member function without an object argument}} + f1(y1); // expected-error {{call to non-static member function without an object argument}} + f1(y2); // expected-error {{call to non-static member function without an object argument}} + g1(0); + g1(z); + g1(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g1(x2); // expected-error {{invalid use of member 'x2' in static member function}} + g1(y0); + g1(y1); + g1(y2); + + f2(0); // expected-error {{call to non-static member function without an object argument}} + f2(z); // expected-error {{call to non-static member function without an object argument}} + f2(x0); // expected-error {{call to non-static member function without an object argument}} + f2(x1); // expected-error {{call to non-static member function without an object argument}} + f2(x2); // expected-error {{call to non-static member function without an object argument}} + f2(y0); // expected-error {{call to non-static member function without an object argument}} + f2(y1); // expected-error {{call to non-static member function without an object argument}} + f2(y2); // expected-error {{call to non-static member function without an object argument}} + g2(0); + g2(z); + g2(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g2(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g2(x2); // expected-error {{invalid use of member 'x2' in static member function}} + g2(y0); + g2(y1); + g2(y2); + } + }; + + template struct D; // expected-note 2{{in instantiation of}} + + template + struct E : T { + int x1; + static inline int y1; + + int f1(int); + static int g1(int); + + using T::x0; + using T::y0; + using T::f0; + using T::g0; + + template + void non_static_spec(U); + + template + static void static_spec(U); + + template<> + void non_static_spec(int z) { + ++z; + ++x0; + ++x1; + ++y0; + ++y1; + + &z; + &x0; + &x1; + &y0; + &y1; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + + &T::x0; + &E::x1; + &T::y0; + &E::y1; + &T::f0; + &E::f1; + &T::g0; + &E::g1; + + f0(0); + f0(z); + f0(x0); + f0(x1); + f0(y0); + f0(y1); + g0(0); + g0(z); + g0(x0); + g0(x1); + g0(y0); + g0(y1); + + f1(0); + f1(z); + f1(x0); + f1(x1); + f1(y0); + f1(y1); + g1(0); + g1(z); + g1(x0); + g1(x1); + g1(y0); + g1(y1); + } + + template<> + void static_spec(int z) { + ++z; + ++x0; // expected-error {{invalid use of member 'x0' in static member function}} + ++x1; // expected-error {{invalid use of member 'x1' in static member function}} + ++y0; + ++y1; + + &z; + &x0; // expected-error {{invalid use of member 'x0' in static member function}} + &x1; // expected-error {{invalid use of member 'x1' in static member function}} + &y0; + &y1; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + + &T::x0; + &E::x1; + &T::y0; + &E::y1; + &T::f0; + &E::f1; + &T::g0; + &E::g1; + + f0(0); // expected-error {{call to non-static member function without an object argument}} + f0(z); // expected-error {{call to non-static member function without an object argument}} + f0(x0); // expected-error {{call to non-static member function without an object argument}} + f0(x1); // expected-error {{call to non-static member function without an object argument}} + f0(y0); // expected-error {{call to non-static member function without an object argument}} + f0(y1); // expected-error {{call to non-static member function without an object argument}} + g0(0); + g0(z); + g0(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g0(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g0(y0); + g0(y1); + + f1(0); // expected-error {{call to non-static member function without an object argument}} + f1(z); // expected-error {{call to non-static member function without an object argument}} + f1(x0); // expected-error {{call to non-static member function without an object argument}} + f1(x1); // expected-error {{call to non-static member function without an object argument}} + f1(y0); // expected-error {{call to non-static member function without an object argument}} + f1(y1); // expected-error {{call to non-static member function without an object argument}} + g1(0); + g1(z); + g1(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g1(y0); + g1(y1); + } + }; + + template struct E; // expected-note 2{{in instantiation of}} + +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index cbc1d85bb33dfc39048a04a57095c4b96b53f103..74163f30e19b1dca7fae73c145b5bef39cccada5 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2803,6 +2803,10 @@ void OpenACCClauseEnqueue::VisitVectorLengthClause( const OpenACCVectorLengthClause &C) { Visitor.AddStmt(C.getIntExpr()); } +void OpenACCClauseEnqueue::VisitNumGangsClause(const OpenACCNumGangsClause &C) { + for (Expr *IE : C.getIntExprs()) + Visitor.AddStmt(IE); +} } // namespace void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index acc596fef87b7600f630c4c97184ffe9c4b7e119..4ee64de697d37ad9d16c851e9c7a31b4fb500a37 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6721,6 +6721,23 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) { EXPECT_FALSE(FromL->isDependentLambda()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) { + Decl *From, *To; + std::tie(From, To) = getImportedDecl( + R"( + void foo() { + (void) []() { + struct X {}; + return X(); + }; + } + )", + Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only + auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr()); + EXPECT_TRUE(ToLambda); +} + TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) { Decl *FromTU = getTuDecl( R"( diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h index e3c7ff685f5724bf92b8a4da10a189868077d7c5..3b0e05ed72220e579254f713ec6de9f7773abc30 100644 --- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -456,7 +456,7 @@ const IndirectFieldDecl *findIndirectFieldDecl(ASTContext &ASTCtx, /// Requirements: /// /// `Name` must be unique in `ASTCtx`. -template +template LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env, llvm::StringRef Name) { const ValueDecl *VD = findValueDecl(ASTCtx, Name); @@ -470,7 +470,7 @@ LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env, /// Requirements: /// /// `Name` must be unique in `ASTCtx`. -template +template ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env, llvm::StringRef Name) { const ValueDecl *VD = findValueDecl(ASTCtx, Name); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index bb16138126c8f973ad1b184b6b0b7ff617f9d5ff..215e208615ac239d1d6f3ba489c3bf8691698125 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -3637,7 +3637,7 @@ TEST(TransferTest, VarDeclInitAssignConditionalOperator) { }; void target(A Foo, A Bar, bool Cond) { - A Baz = Cond ? Foo : Bar; + A Baz = Cond ? A(Foo) : A(Bar); // Make sure A::i is modeled. Baz.i; /*[[p]]*/ @@ -5275,6 +5275,67 @@ TEST(TransferTest, BinaryOperatorComma) { }); } +TEST(TransferTest, ConditionalOperatorValue) { + std::string Code = R"( + void target(bool Cond, bool B1, bool B2) { + bool JoinSame = Cond ? B1 : B1; + bool JoinDifferent = Cond ? B1 : B2; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); + + auto &B1 = getValueForDecl(ASTCtx, Env, "B1"); + auto &B2 = getValueForDecl(ASTCtx, Env, "B2"); + auto &JoinSame = getValueForDecl(ASTCtx, Env, "JoinSame"); + auto &JoinDifferent = + getValueForDecl(ASTCtx, Env, "JoinDifferent"); + + EXPECT_EQ(&JoinSame, &B1); + + const Formula &JoinDifferentEqB1 = + Env.arena().makeEquals(JoinDifferent.formula(), B1.formula()); + EXPECT_TRUE(Env.allows(JoinDifferentEqB1)); + EXPECT_FALSE(Env.proves(JoinDifferentEqB1)); + + const Formula &JoinDifferentEqB2 = + Env.arena().makeEquals(JoinDifferent.formula(), B2.formula()); + EXPECT_TRUE(Env.allows(JoinDifferentEqB2)); + EXPECT_FALSE(Env.proves(JoinDifferentEqB1)); + }); +} + +TEST(TransferTest, ConditionalOperatorLocation) { + std::string Code = R"( + void target(bool Cond, int I1, int I2) { + int &JoinSame = Cond ? I1 : I1; + int &JoinDifferent = Cond ? I1 : I2; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); + + StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1"); + StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2"); + StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame"); + StorageLocation &JoinDifferent = + getLocForDecl(ASTCtx, Env, "JoinDifferent"); + + EXPECT_EQ(&JoinSame, &I1); + + EXPECT_NE(&JoinDifferent, &I1); + EXPECT_NE(&JoinDifferent, &I2); + }); +} + TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { std::string Code = R"( void target(bool Foo) { @@ -5522,10 +5583,7 @@ TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { auto *Loc = Env.getReturnStorageLocation(); EXPECT_THAT(Loc, NotNull()); - // TODO: We would really like to make this stronger assertion, but that - // doesn't work because we don't propagate values correctly through - // the conditional operator yet. - // EXPECT_EQ(Loc, SLoc); + EXPECT_EQ(Loc, SLoc); }, {BuiltinOptions{ContextSensitiveOptions{}}}); } diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 4f445c64ab303a2d050630307d58f9e86025d95c..34999b7376397b62c74f239f18da88544fa0308d 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -599,6 +599,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) { ASSERT_EQ(Tokens.size(), 6u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_CastRParen); + Tokens = annotate("(uint32_t)&&label;"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_CastRParen); + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_UnaryOperator); + EXPECT_TOKEN(Tokens[4], tok::identifier, TT_Unknown); + Tokens = annotate("auto x = (Foo)p;"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_CastRParen); diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 765cbbf3b04bcfad900404aa0246ba0d2e37a6c8..0d1365f09291e0252ae08fb4d6ddaf35120aa618 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -107,7 +107,7 @@ static std::string ReadPCHRecord(StringRef type) { return StringSwitch(type) .EndsWith("Decl *", "Record.GetLocalDeclAs<" + std::string(type.data(), 0, type.size() - 1) + - ">(Record.readInt())") + ">(LocalDeclID(Record.readInt()))") .Case("TypeSourceInfo *", "Record.readTypeSourceInfo()") .Case("Expr *", "Record.readExpr()") .Case("IdentifierInfo *", "Record.readIdentifier()") @@ -1618,7 +1618,7 @@ writePrettyPrintFunction(const Record &R, Spelling += Namespace; Spelling += " "; } - } else if (Variety == "HLSLSemantic") { + } else if (Variety == "HLSLAnnotation") { Prefix = ":"; Suffix = ""; } else { @@ -3608,7 +3608,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { // and declspecs. Then generate a big switch statement for each of them. std::vector Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector> Declspec, Microsoft, - GNU, Pragma, HLSLSemantic; + GNU, Pragma, HLSLAnnotation; std::map>> CXX, C23; @@ -3631,8 +3631,8 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { C23[SI.nameSpace()].emplace_back(R, SI); else if (Variety == "Pragma") Pragma.emplace_back(R, SI); - else if (Variety == "HLSLSemantic") - HLSLSemantic.emplace_back(R, SI); + else if (Variety == "HLSLAnnotation") + HLSLAnnotation.emplace_back(R, SI); } } @@ -3650,9 +3650,9 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "case AttributeCommonInfo::Syntax::AS_Pragma:\n"; OS << " return llvm::StringSwitch(Name)\n"; GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); - OS << "case AttributeCommonInfo::Syntax::AS_HLSLSemantic:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_HLSLAnnotation:\n"; OS << " return llvm::StringSwitch(Name)\n"; - GenerateHasAttrSpellingStringSwitch(HLSLSemantic, OS, "HLSLSemantic"); + GenerateHasAttrSpellingStringSwitch(HLSLAnnotation, OS, "HLSLAnnotation"); auto fn = [&OS](const char *Spelling, const std::map< std::string, @@ -4669,7 +4669,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { std::vector Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector GNU, Declspec, Microsoft, CXX11, - Keywords, Pragma, C23, HLSLSemantic; + Keywords, Pragma, C23, HLSLAnnotation; std::set Seen; for (const auto *A : Attrs) { const Record &Attr = *A; @@ -4720,8 +4720,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { Matches = &Keywords; else if (Variety == "Pragma") Matches = &Pragma; - else if (Variety == "HLSLSemantic") - Matches = &HLSLSemantic; + else if (Variety == "HLSLAnnotation") + Matches = &HLSLAnnotation; assert(Matches && "Unsupported spelling variety found"); @@ -4757,8 +4757,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { StringMatcher("Name", Keywords, OS).Emit(); OS << " } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n"; StringMatcher("Name", Pragma, OS).Emit(); - OS << " } else if (AttributeCommonInfo::AS_HLSLSemantic == Syntax) {\n"; - StringMatcher("Name", HLSLSemantic, OS).Emit(); + OS << " } else if (AttributeCommonInfo::AS_HLSLAnnotation == Syntax) {\n"; + StringMatcher("Name", HLSLAnnotation, OS).Emit(); OS << " }\n"; OS << " return AttributeCommonInfo::UnknownAttribute;\n" << "}\n"; @@ -4876,7 +4876,7 @@ enum class SpellingKind : size_t { Microsoft, Keyword, Pragma, - HLSLSemantic, + HLSLAnnotation, NumSpellingKinds }; static const size_t NumSpellingKinds = (size_t)SpellingKind::NumSpellingKinds; @@ -4890,15 +4890,16 @@ public: } void add(const Record &Attr, FlattenedSpelling Spelling) { - SpellingKind Kind = StringSwitch(Spelling.variety()) - .Case("GNU", SpellingKind::GNU) - .Case("CXX11", SpellingKind::CXX11) - .Case("C23", SpellingKind::C23) - .Case("Declspec", SpellingKind::Declspec) - .Case("Microsoft", SpellingKind::Microsoft) - .Case("Keyword", SpellingKind::Keyword) - .Case("Pragma", SpellingKind::Pragma) - .Case("HLSLSemantic", SpellingKind::HLSLSemantic); + SpellingKind Kind = + StringSwitch(Spelling.variety()) + .Case("GNU", SpellingKind::GNU) + .Case("CXX11", SpellingKind::CXX11) + .Case("C23", SpellingKind::C23) + .Case("Declspec", SpellingKind::Declspec) + .Case("Microsoft", SpellingKind::Microsoft) + .Case("Keyword", SpellingKind::Keyword) + .Case("Pragma", SpellingKind::Pragma) + .Case("HLSLAnnotation", SpellingKind::HLSLAnnotation); std::string Name; if (!Spelling.nameSpace().empty()) { switch (Kind) { @@ -5007,7 +5008,8 @@ static void WriteDocumentation(RecordKeeper &Records, // so it must be last. OS << ".. csv-table:: Supported Syntaxes\n"; OS << " :header: \"GNU\", \"C++11\", \"C23\", \"``__declspec``\","; - OS << " \"Keyword\", \"``#pragma``\", \"HLSL Semantic\", \"``#pragma clang "; + OS << " \"Keyword\", \"``#pragma``\", \"HLSL Annotation\", \"``#pragma " + "clang "; OS << "attribute``\"\n\n \""; for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) { SpellingKind K = (SpellingKind)Kind; diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 88e7b6e8546595b9ff50ef777736c498a80907c1..c455071ed9da7ca92d07267b124ca03fff1f7bf9 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -658,9 +658,9 @@ public: std::vector Args; std::set AddressArgs; std::map IntegerArgs; - IRBuilderResult(StringRef CallPrefix, std::vector Args, - std::set AddressArgs, - std::map IntegerArgs) + IRBuilderResult(StringRef CallPrefix, const std::vector &Args, + const std::set &AddressArgs, + const std::map &IntegerArgs) : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs), IntegerArgs(IntegerArgs) {} void genCode(raw_ostream &OS, @@ -727,8 +727,9 @@ public: std::string IntrinsicID; std::vector ParamTypes; std::vector Args; - IRIntrinsicResult(StringRef IntrinsicID, std::vector ParamTypes, - std::vector Args) + IRIntrinsicResult(StringRef IntrinsicID, + const std::vector &ParamTypes, + const std::vector &Args) : IntrinsicID(std::string(IntrinsicID)), ParamTypes(ParamTypes), Args(Args) {} void genCode(raw_ostream &OS, diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 8649507ce1c79bb3577513a3f3e1aa4f92f36c21..6ce451e3cac2e3048a9a7ce4822d2aa46e9b70b1 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -50,6 +50,8 @@ option(COMPILER_RT_BUILD_LIBFUZZER "Build libFuzzer" ON) mark_as_advanced(COMPILER_RT_BUILD_LIBFUZZER) option(COMPILER_RT_BUILD_PROFILE "Build profile runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_PROFILE) +option(COMPILER_RT_BUILD_CTX_PROFILE "Build ctx profile runtime" ON) +mark_as_advanced(COMPILER_RT_BUILD_CTX_PROFILE) option(COMPILER_RT_BUILD_MEMPROF "Build memory profiling runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_MEMPROF) option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" OFF) diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index 423171532c20288a7daed51da4e236e89b5ac80e..2fe06273a814c709041bd1d88493a1c778a84e8b 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -66,6 +66,7 @@ set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} ${RISCV32} ${RISCV64} ${LOONGARCH64}) +set(ALL_CTX_PROFILE_SUPPORTED_ARCH ${X86_64}) set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X} ${LOONGARCH64} ${RISCV64}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index b281ac64f5d5c72db22bf73b7b57a36a2f8509d2..ba740af9e1d60f7db4b3c35b3a92905af191bfce 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -632,6 +632,9 @@ if(APPLE) list_intersect(PROFILE_SUPPORTED_ARCH ALL_PROFILE_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) + list_intersect(CTX_PROFILE_SUPPORTED_ARCH + ALL_CTX_PROFILE_SUPPORTED_ARCH + SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(TSAN_SUPPORTED_ARCH ALL_TSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -678,6 +681,7 @@ else() filter_available_targets(HWASAN_SUPPORTED_ARCH ${ALL_HWASAN_SUPPORTED_ARCH}) filter_available_targets(MEMPROF_SUPPORTED_ARCH ${ALL_MEMPROF_SUPPORTED_ARCH}) filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH}) + filter_available_targets(CTX_PROFILE_SUPPORTED_ARCH ${ALL_CTX_PROFILE_SUPPORTED_ARCH}) filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH}) filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH}) filter_available_targets(SAFESTACK_SUPPORTED_ARCH @@ -803,6 +807,13 @@ else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() +if (COMPILER_RT_HAS_SANITIZER_COMMON AND CTX_PROFILE_SUPPORTED_ARCH AND + OS_NAME MATCHES "Linux") + set(COMPILER_RT_HAS_CTX_PROFILE TRUE) +else() + set(COMPILER_RT_HAS_CTX_PROFILE FALSE) +endif() + if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH) if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD") set(COMPILER_RT_HAS_TSAN TRUE) diff --git a/compiler-rt/lib/CMakeLists.txt b/compiler-rt/lib/CMakeLists.txt index 43ba9a102c848717fd14e5896dbd246617a518d9..f9e96563b8809072c711423a9ea49ac4c50a2714 100644 --- a/compiler-rt/lib/CMakeLists.txt +++ b/compiler-rt/lib/CMakeLists.txt @@ -51,6 +51,10 @@ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) compiler_rt_build_runtime(profile) endif() +if(COMPILER_RT_BUILD_CTX_PROFILE AND COMPILER_RT_HAS_CTX_PROFILE) + compiler_rt_build_runtime(ctx_profile) +endif() + if(COMPILER_RT_BUILD_XRAY) compiler_rt_build_runtime(xray) endif() diff --git a/compiler-rt/lib/builtins/fp_add_impl.inc b/compiler-rt/lib/builtins/fp_add_impl.inc index 7133358df9bd2cbaaac0b7c26bbc3b58075ca2c1..d20599921e7d88a3d1bc5ef21bc58cee312809e4 100644 --- a/compiler-rt/lib/builtins/fp_add_impl.inc +++ b/compiler-rt/lib/builtins/fp_add_impl.inc @@ -91,7 +91,7 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) { // Shift the significand of b by the difference in exponents, with a sticky // bottom bit to get rounding correct. - const unsigned int align = aExponent - bExponent; + const unsigned int align = (unsigned int)(aExponent - bExponent); if (align) { if (align < typeWidth) { const bool sticky = (bSignificand << (typeWidth - align)) != 0; diff --git a/compiler-rt/lib/builtins/fp_fixint_impl.inc b/compiler-rt/lib/builtins/fp_fixint_impl.inc index 3556bad9990b2fd53169e538e60348863d784296..2f2f77ce781ae278fee43151e1b9e4733817e6b4 100644 --- a/compiler-rt/lib/builtins/fp_fixint_impl.inc +++ b/compiler-rt/lib/builtins/fp_fixint_impl.inc @@ -34,7 +34,7 @@ static __inline fixint_t __fixint(fp_t a) { // If 0 <= exponent < significandBits, right shift to get the result. // Otherwise, shift left. if (exponent < significandBits) - return sign * (significand >> (significandBits - exponent)); + return (fixint_t)(sign * (significand >> (significandBits - exponent))); else - return sign * ((fixuint_t)significand << (exponent - significandBits)); + return (fixint_t)(sign * ((fixuint_t)significand << (exponent - significandBits))); } diff --git a/compiler-rt/lib/builtins/fp_lib.h b/compiler-rt/lib/builtins/fp_lib.h index c4f0a5b9587f777c7663767ab1645255310c70af..8404d98c9350810562bd0801ac125f889bae39b0 100644 --- a/compiler-rt/lib/builtins/fp_lib.h +++ b/compiler-rt/lib/builtins/fp_lib.h @@ -43,8 +43,8 @@ static __inline int rep_clz(rep_t a) { return clzsi(a); } // 32x32 --> 64 bit multiply static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) { const uint64_t product = (uint64_t)a * b; - *hi = product >> 32; - *lo = product; + *hi = (rep_t)(product >> 32); + *lo = (rep_t)product; } COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b); @@ -239,7 +239,7 @@ static __inline int normalize(rep_t *significand) { return 1 - shift; } -static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) { +static __inline void wideLeftShift(rep_t *hi, rep_t *lo, unsigned int count) { *hi = *hi << count | *lo >> (typeWidth - count); *lo = *lo << count; } diff --git a/compiler-rt/lib/builtins/int_types.h b/compiler-rt/lib/builtins/int_types.h index ca97391fc28466b9c4f1921c3ae014262a8f8485..48862f3642175bd241e97805c7d32111febe2c28 100644 --- a/compiler-rt/lib/builtins/int_types.h +++ b/compiler-rt/lib/builtins/int_types.h @@ -107,8 +107,8 @@ typedef union { static __inline ti_int make_ti(di_int h, di_int l) { twords r; - r.s.high = h; - r.s.low = l; + r.s.high = (du_int)h; + r.s.low = (du_int)l; return r.all; } diff --git a/compiler-rt/lib/ctx_profile/CMakeLists.txt b/compiler-rt/lib/ctx_profile/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..80e71acc38f8a1fc161a81e2f30c0231d71e3794 --- /dev/null +++ b/compiler-rt/lib/ctx_profile/CMakeLists.txt @@ -0,0 +1,19 @@ +add_compiler_rt_component(ctx_profile) + +set(CTX_PROFILE_SOURCES + CtxInstrProfiling.cpp + ) + +set(CTX_PROFILE_HEADERS + CtxInstrProfiling.h + ) + +include_directories(..) +include_directories(../../include) + +# We don't use the C++ Standard Library here, so avoid including it by mistake. +append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ EXTRA_FLAGS) + +if(COMPILER_RT_INCLUDE_TESTS) + add_subdirectory(tests) +endif() diff --git a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7620ce92f7ebdec720b97e6eff44af44103b1aad --- /dev/null +++ b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp @@ -0,0 +1,40 @@ +//===- CtxInstrProfiling.cpp - contextual instrumented PGO ----------------===// +// +// 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 "CtxInstrProfiling.h" +#include "sanitizer_common/sanitizer_allocator_internal.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_dense_map.h" +#include "sanitizer_common/sanitizer_mutex.h" +#include "sanitizer_common/sanitizer_placement_new.h" +#include "sanitizer_common/sanitizer_thread_safety.h" + +#include + +using namespace __ctx_profile; + +// FIXME(mtrofin): use malloc / mmap instead of sanitizer common APIs to reduce +// the dependency on the latter. +Arena *Arena::allocateNewArena(size_t Size, Arena *Prev) { + assert(!Prev || Prev->Next == nullptr); + Arena *NewArena = + new (__sanitizer::InternalAlloc(Size + sizeof(Arena))) Arena(Size); + if (Prev) + Prev->Next = NewArena; + return NewArena; +} + +void Arena::freeArenaList(Arena *&A) { + assert(A); + for (auto *I = A; I != nullptr;) { + auto *Current = I; + I = I->Next; + __sanitizer::InternalFree(Current); + } + A = nullptr; +} diff --git a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h new file mode 100644 index 0000000000000000000000000000000000000000..c1789c32a64c253da8d1156f00fd6222a8e21b25 --- /dev/null +++ b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h @@ -0,0 +1,55 @@ +/*===- CtxInstrProfiling.h- Contextual instrumentation-based PGO ---------===*\ +|* +|* 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 CTX_PROFILE_CTXINSTRPROFILING_H_ +#define CTX_PROFILE_CTXINSTRPROFILING_H_ + +#include + +namespace __ctx_profile { + +/// Arena (bump allocator) forming a linked list. Intentionally not thread safe. +/// Allocation and de-allocation happen using sanitizer APIs. We make that +/// explicit. +class Arena final { +public: + // When allocating a new Arena, optionally specify an existing one to append + // to, assumed to be the last in the Arena list. We only need to support + // appending to the arena list. + static Arena *allocateNewArena(size_t Size, Arena *Prev = nullptr); + static void freeArenaList(Arena *&A); + + uint64_t size() const { return Size; } + + // Allocate S bytes or return nullptr if we don't have that many available. + char *tryBumpAllocate(size_t S) { + if (Pos + S > Size) + return nullptr; + Pos += S; + return start() + (Pos - S); + } + + Arena *next() const { return Next; } + + // the beginning of allocatable memory. + const char *start() const { return const_cast(this)->start(); } + const char *pos() const { return start() + Pos; } + +private: + explicit Arena(uint32_t Size) : Size(Size) {} + ~Arena() = delete; + + char *start() { return reinterpret_cast(&this[1]); } + + Arena *Next = nullptr; + uint64_t Pos = 0; + const uint64_t Size; +}; + +} // namespace __ctx_profile +#endif // CTX_PROFILE_CTXINSTRPROFILING_H_ diff --git a/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt b/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..012fd7aff7862363eb10ec498f22f79e02d4421e --- /dev/null +++ b/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt @@ -0,0 +1,82 @@ +include(CheckCXXCompilerFlag) +include(CompilerRTCompile) +include(CompilerRTLink) + +set(CTX_PROFILE_UNITTEST_CFLAGS + ${COMPILER_RT_UNITTEST_CFLAGS} + ${COMPILER_RT_GTEST_CFLAGS} + ${COMPILER_RT_GMOCK_CFLAGS} + ${SANITIZER_TEST_CXX_CFLAGS} + -I${COMPILER_RT_SOURCE_DIR}/lib/ + -DSANITIZER_COMMON_NO_REDEFINE_BUILTINS + -O2 + -g + -fno-rtti + -Wno-pedantic + -fno-omit-frame-pointer) + +# Suppress warnings for gmock variadic macros for clang and gcc respectively. +append_list_if(SUPPORTS_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS_FLAG -Wno-gnu-zero-variadic-macro-arguments CTX_PROFILE_UNITTEST_CFLAGS) +append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros CTX_PROFILE_UNITTEST_CFLAGS) + +file(GLOB CTX_PROFILE_HEADERS ../*.h) + +set(CTX_PROFILE_SOURCES + ../CtxInstrProfiling.cpp) + +set(CTX_PROFILE_UNITTESTS + CtxInstrProfilingTest.cpp + driver.cpp) + +include_directories(../../../include) + +set(CTX_PROFILE_UNITTEST_HEADERS + ${CTX_PROFILE_HEADERS}) + +set(CTX_PROFILE_UNITTEST_LINK_FLAGS + ${COMPILER_RT_UNITTEST_LINK_FLAGS}) + +list(APPEND CTX_PROFILE_UNITTEST_LINK_FLAGS -pthread) + +set(CTX_PROFILE_UNITTEST_DEPS) +if (TARGET cxx-headers OR HAVE_LIBCXX) + list(APPEND CTX_PROFILE_UNITTEST_DEPS cxx-headers) +endif() + +set(CTX_PROFILE_UNITTEST_LINK_LIBRARIES + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_TEST_CXX_LIBRARIES}) +append_list_if(COMPILER_RT_HAS_LIBDL -ldl CTX_PROFILE_UNITTEST_LINK_LIBRARIES) + +macro (add_ctx_profile_tests_for_arch arch) + set(CTX_PROFILE_TEST_RUNTIME_OBJECTS + $ + $ + $ + $ + $ + ) + set(CTX_PROFILE_TEST_RUNTIME RTCtxProfileTest.${arch}) + add_library(${CTX_PROFILE_TEST_RUNTIME} STATIC ${CTX_PROFILE_TEST_RUNTIME_OBJECTS}) + set_target_properties(${CTX_PROFILE_TEST_RUNTIME} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + FOLDER "Compiler-RT Runtime tests") + set(CTX_PROFILE_TEST_OBJECTS) + generate_compiler_rt_tests(CTX_PROFILE_TEST_OBJECTS + CtxProfileUnitTests "CtxProfile-${arch}-UnitTest" ${arch} + RUNTIME ${CTX_PROFILE_TEST_RUNTIME} + DEPS ${CTX_PROFILE_UNITTEST_DEPS} + SOURCES ${CTX_PROFILE_UNITTESTS} ${CTX_PROFILE_SOURCES} ${COMPILER_RT_GTEST_SOURCE} + COMPILE_DEPS ${CTX_PROFILE_UNITTEST_HEADERS} + CFLAGS ${CTX_PROFILE_UNITTEST_CFLAGS} + LINK_FLAGS ${CTX_PROFILE_UNITTEST_LINK_FLAGS} ${CTX_PROFILE_UNITTEST_LINK_LIBRARIES}) +endmacro() + +add_custom_target(CtxProfileUnitTests) +set_target_properties(CtxProfileUnitTests PROPERTIES FOLDER "Compiler-RT Tests") +if(COMPILER_RT_CAN_EXECUTE_TESTS AND COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST CTX_PROFILE_SUPPORTED_ARCH) + # CtxProfile unit tests are only run on the host machine. + foreach(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) + add_ctx_profile_tests_for_arch(${arch}) + endforeach() +endif() diff --git a/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp b/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44f37d2576320624301537cfe00aaa7e5390f0f8 --- /dev/null +++ b/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp @@ -0,0 +1,22 @@ +#include "../CtxInstrProfiling.h" +#include "gtest/gtest.h" + +using namespace __ctx_profile; + +TEST(ArenaTest, Basic) { + Arena *A = Arena::allocateNewArena(1024); + EXPECT_EQ(A->size(), 1024U); + EXPECT_EQ(A->next(), nullptr); + + auto *M1 = A->tryBumpAllocate(1020); + EXPECT_NE(M1, nullptr); + auto *M2 = A->tryBumpAllocate(4); + EXPECT_NE(M2, nullptr); + EXPECT_EQ(M1 + 1020, M2); + EXPECT_EQ(A->tryBumpAllocate(1), nullptr); + Arena *A2 = Arena::allocateNewArena(2024, A); + EXPECT_EQ(A->next(), A2); + EXPECT_EQ(A2->next(), nullptr); + Arena::freeArenaList(A); + EXPECT_EQ(A, nullptr); +} diff --git a/libc/test/UnitTest/PigweedTest.h b/compiler-rt/lib/ctx_profile/tests/driver.cpp similarity index 50% rename from libc/test/UnitTest/PigweedTest.h rename to compiler-rt/lib/ctx_profile/tests/driver.cpp index 855633527fb3596edc4f043eeb6c83fd565a87f7..b402cec1126b33b94f3884f2847a3113968fd6dd 100644 --- a/libc/test/UnitTest/PigweedTest.h +++ b/compiler-rt/lib/ctx_profile/tests/driver.cpp @@ -1,4 +1,4 @@ -//===-- Header for setting up the Pigweed tests -----------------*- C++ -*-===// +//===-- driver.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. @@ -6,13 +6,9 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_UTILS_UNITTEST_PIGWEEDTEST_H -#define LLVM_LIBC_UTILS_UNITTEST_PIGWEEDTEST_H +#include "gtest/gtest.h" -#include - -namespace LIBC_NAMESPACE::testing { -using Test = ::testing::Test; +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } - -#endif // LLVM_LIBC_UTILS_UNITTEST_PIGWEEDTEST_H diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.h b/compiler-rt/lib/scudo/standalone/allocator_config.h index 1e0cf1015ba67e8d9a40be609b21efdccbe22949..60f59bdd2f4c3e5ca95a64ba326903fa74433d54 100644 --- a/compiler-rt/lib/scudo/standalone/allocator_config.h +++ b/compiler-rt/lib/scudo/standalone/allocator_config.h @@ -146,6 +146,7 @@ struct FuchsiaConfig { // Support 39-bit VMA for riscv-64 static const uptr RegionSizeLog = 28U; static const uptr GroupSizeLog = 19U; + static const bool EnableContiguousRegions = false; #else static const uptr RegionSizeLog = 30U; static const uptr GroupSizeLog = 21U; diff --git a/compiler-rt/test/gwp_asan/CMakeLists.txt b/compiler-rt/test/gwp_asan/CMakeLists.txt index 86260027426feb1283385f94290932b9e0ab2f5e..eda23cd93d6c372042ceea85a8144cceac4469d3 100644 --- a/compiler-rt/test/gwp_asan/CMakeLists.txt +++ b/compiler-rt/test/gwp_asan/CMakeLists.txt @@ -35,9 +35,9 @@ if (COMPILER_RT_INCLUDE_TESTS AND COMPILER_RT_HAS_SCUDO_STANDALONE AND COMPILER_ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py) list(APPEND GWP_ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) endforeach() -endif() -add_lit_testsuite(check-gwp_asan "Running the GWP-ASan tests" - ${GWP_ASAN_TESTSUITES} - DEPENDS ${GWP_ASAN_TEST_DEPS}) -set_target_properties(check-gwp_asan PROPERTIES FOLDER "Compiler-RT Misc") + add_lit_testsuite(check-gwp_asan "Running the GWP-ASan tests" + ${GWP_ASAN_TESTSUITES} + DEPENDS ${GWP_ASAN_TEST_DEPS}) + set_target_properties(check-gwp_asan PROPERTIES FOLDER "Compiler-RT Misc") +endif() diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 71141e5efac4888cb03b32f2aa0bcc891f892f66..c8e75024823f2cc98f4dacc0bc9125f588e216fe 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -81,12 +81,13 @@ if (FLANG_STANDALONE_BUILD) mark_as_advanced(LLVM_ENABLE_ASSERTIONS) endif() - # We need a pre-built/installed version of LLVM. - find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}") # If the user specifies a relative path to LLVM_DIR, the calls to include # LLVM modules fail. Append the absolute path to LLVM_DIR instead. - get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} REALPATH) + get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} + REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR_ABSOLUTE}) + # We need a pre-built/installed version of LLVM. + find_package(LLVM REQUIRED HINTS "${LLVM_DIR_ABSOLUTE}") # Users might specify a path to CLANG_DIR that's: # * a full path, or @@ -97,7 +98,7 @@ if (FLANG_STANDALONE_BUILD) CLANG_DIR_ABSOLUTE ${CLANG_DIR} REALPATH - ${CMAKE_CURRENT_SOURCE_DIR}) + BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${CLANG_DIR_ABSOLUTE}) # TODO: Remove when libclangDriver is lifted out of Clang @@ -124,13 +125,14 @@ if (FLANG_STANDALONE_BUILD) include(AddClang) include(TableGen) - find_package(MLIR REQUIRED CONFIG) - # Use SYSTEM for the same reasons as for LLVM includes - include_directories(SYSTEM ${MLIR_INCLUDE_DIRS}) # If the user specifies a relative path to MLIR_DIR, the calls to include # MLIR modules fail. Append the absolute path to MLIR_DIR instead. - get_filename_component(MLIR_DIR_ABSOLUTE ${MLIR_DIR} REALPATH) + get_filename_component(MLIR_DIR_ABSOLUTE ${MLIR_DIR} + REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${MLIR_DIR_ABSOLUTE}) + find_package(MLIR REQUIRED CONFIG HINTS ${MLIR_DIR_ABSOLUTE}) + # Use SYSTEM for the same reasons as for LLVM includes + include_directories(SYSTEM ${MLIR_INCLUDE_DIRS}) include(AddMLIR) find_program(MLIR_TABLEGEN_EXE "mlir-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index 814f3eb12cfcbc5fe2f4557c8f4b139164b8b04f..ac120b4ff09b6d0b9e9aa07b43293813ca1082eb 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -266,26 +266,6 @@ is `ParseSyntaxOnlyAction`, which corresponds to `-fsyntax-only`. In other words, `flang-new -fc1 ` is equivalent to `flang-new -fc1 -fsyntax-only `. -## The `flang-to-external-fc` script -The `flang-to-external-fc` wrapper script for `flang-new` was introduced as a -development tool and to facilitate testing. The `flang-to-external-fc` wrapper -script will: -* use `flang-new` to unparse the input source file (i.e. it will run `flang-new - -fc1 -fdebug-unparse `), and then -* call a host Fortran compiler, e.g. `gfortran`, to compile the unparsed file. - -Here's a basic breakdown of what happens inside `flang-to-external-fc` when you -run `flang-to-external-fc file.f90`: -```bash -flang-new -fc1 -fdebug-unparse file.f90 -o file-unparsed.f90 -gfortran file-unparsed.f90 -``` -This is a simplified version for illustration purposes only. In practice, -`flang-to-external-fc` adds a few more frontend options and it also supports -various other use cases (e.g. compiling C files, linking existing object -files). `gfortran` is the default host compiler used by `flang-to-external-fc`. -You can change it by setting the `FLANG_FC` environment variable. - ## Adding new Compiler Options Adding a new compiler option in Flang consists of two steps: * define the new option in a dedicated TableGen file, diff --git a/flang/include/flang/Common/real.h b/flang/include/flang/Common/real.h index 49c400b368a2c190b1dfce18424d3115320070e8..b527deda0e3b4f8dc3414cba516f174104fe37f5 100644 --- a/flang/include/flang/Common/real.h +++ b/flang/include/flang/Common/real.h @@ -108,7 +108,27 @@ static constexpr int PrecisionOfRealKind(int kind) { } } -template class RealDetails { +// RealCharacteristics is constexpr, but also useful when constructed +// with a non-constant precision argument. +class RealCharacteristics { +public: + explicit constexpr RealCharacteristics(int p) : binaryPrecision{p} {} + + int binaryPrecision; + int bits{BitsForBinaryPrecision(binaryPrecision)}; + bool isImplicitMSB{binaryPrecision != 64 /*x87*/}; + int significandBits{binaryPrecision - isImplicitMSB}; + int exponentBits{bits - significandBits - 1 /*sign*/}; + int maxExponent{(1 << exponentBits) - 1}; + int exponentBias{maxExponent / 2}; + int decimalPrecision{LogBaseTwoToLogBaseTen(binaryPrecision - 1)}; + int decimalRange{LogBaseTwoToLogBaseTen(exponentBias - 1)}; + // Number of significant decimal digits in the fraction of the + // exact conversion of the least nonzero subnormal. + int maxDecimalConversionDigits{MaxDecimalConversionDigits(binaryPrecision)}; + int maxHexadecimalConversionDigits{ + MaxHexadecimalConversionDigits(binaryPrecision)}; + private: // Converts bit widths to whole decimal digits static constexpr int LogBaseTwoToLogBaseTen(int logb2) { @@ -118,33 +138,6 @@ private: (logb2 * LogBaseTenOfTwoTimesTenToThe12th) / TenToThe12th}; return static_cast(logb10); } - -public: - RT_OFFLOAD_VAR_GROUP_BEGIN - static constexpr int binaryPrecision{BINARY_PRECISION}; - static constexpr int bits{BitsForBinaryPrecision(binaryPrecision)}; - static constexpr bool isImplicitMSB{binaryPrecision != 64 /*x87*/}; - static constexpr int significandBits{binaryPrecision - isImplicitMSB}; - static constexpr int exponentBits{bits - significandBits - 1 /*sign*/}; - static constexpr int maxExponent{(1 << exponentBits) - 1}; - static constexpr int exponentBias{maxExponent / 2}; - - static constexpr int decimalPrecision{ - LogBaseTwoToLogBaseTen(binaryPrecision - 1)}; - static constexpr int decimalRange{LogBaseTwoToLogBaseTen(exponentBias - 1)}; - - // Number of significant decimal digits in the fraction of the - // exact conversion of the least nonzero subnormal. - static constexpr int maxDecimalConversionDigits{ - MaxDecimalConversionDigits(binaryPrecision)}; - - static constexpr int maxHexadecimalConversionDigits{ - MaxHexadecimalConversionDigits(binaryPrecision)}; - RT_OFFLOAD_VAR_GROUP_END - - static_assert(binaryPrecision > 0); - static_assert(exponentBits > 1); - static_assert(exponentBits <= 15); }; } // namespace Fortran::common diff --git a/flang/include/flang/Decimal/binary-floating-point.h b/flang/include/flang/Decimal/binary-floating-point.h index 4919c1f9d240f4cfbc2a41f084f0e579912509c8..1e0cde97d98e611105ebb8e44ac926ce180524b4 100644 --- a/flang/include/flang/Decimal/binary-floating-point.h +++ b/flang/include/flang/Decimal/binary-floating-point.h @@ -30,21 +30,20 @@ enum FortranRounding { RoundCompatible, /* RC: like RN, but ties go away from 0 */ }; -template -class BinaryFloatingPointNumber : public common::RealDetails { +template class BinaryFloatingPointNumber { public: - using Details = common::RealDetails; - using Details::binaryPrecision; - using Details::bits; - using Details::decimalPrecision; - using Details::decimalRange; - using Details::exponentBias; - using Details::exponentBits; - using Details::isImplicitMSB; - using Details::maxDecimalConversionDigits; - using Details::maxExponent; - using Details::maxHexadecimalConversionDigits; - using Details::significandBits; + static constexpr common::RealCharacteristics realChars{BINARY_PRECISION}; + static constexpr int binaryPrecision{BINARY_PRECISION}; + static constexpr int bits{realChars.bits}; + static constexpr int isImplicitMSB{realChars.isImplicitMSB}; + static constexpr int significandBits{realChars.significandBits}; + static constexpr int exponentBits{realChars.exponentBits}; + static constexpr int exponentBias{realChars.exponentBias}; + static constexpr int maxExponent{realChars.maxExponent}; + static constexpr int decimalPrecision{realChars.decimalPrecision}; + static constexpr int decimalRange{realChars.decimalRange}; + static constexpr int maxDecimalConversionDigits{ + realChars.maxDecimalConversionDigits}; using RawType = common::HostUnsignedIntType; static_assert(CHAR_BIT * sizeof(RawType) >= bits); diff --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h index 3d766bc08e58d466a963abd3c709928578cc6742..7531d8a81e808d644abee10c7ce117b286c42d3a 100644 --- a/flang/include/flang/Evaluate/call.h +++ b/flang/include/flang/Evaluate/call.h @@ -287,15 +287,18 @@ public: : ProcedureRef{std::move(p), std::move(a)} {} std::optional GetType() const { - if (auto type{proc_.GetType()}) { + if constexpr (IsLengthlessIntrinsicType) { + return A::GetType(); + } else if (auto type{proc_.GetType()}) { // TODO: Non constant explicit length parameters of PDTs result should // likely be dropped too. This is not as easy as for characters since some // long lived DerivedTypeSpec pointer would need to be created here. It is // not clear if this is causing any issue so far since the storage size of // PDTs is independent of length parameters. return type->DropNonConstantCharacterLength(); + } else { + return std::nullopt; } - return std::nullopt; } }; } // namespace Fortran::evaluate diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index 82c31c0c4043011de61e445c826d6c01fb88472a..8aa065b025a4fa44f8ba6fd4cd78145f7ed0f37f 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -365,7 +365,7 @@ struct Procedure { static std::optional Characterize( const semantics::Symbol &, FoldingContext &); static std::optional Characterize( - const ProcedureDesignator &, FoldingContext &); + const ProcedureDesignator &, FoldingContext &, bool emitError); static std::optional Characterize( const ProcedureRef &, FoldingContext &); static std::optional Characterize( diff --git a/flang/include/flang/Evaluate/complex.h b/flang/include/flang/Evaluate/complex.h index 200965ed92121ffaa0d50aa5f499e938edc8f20f..06eef842410944ae15bda63f4a27a8e050c4a182 100644 --- a/flang/include/flang/Evaluate/complex.h +++ b/flang/include/flang/Evaluate/complex.h @@ -104,7 +104,7 @@ extern template class Complex, 11>>; extern template class Complex, 8>>; extern template class Complex, 24>>; extern template class Complex, 53>>; -extern template class Complex, 64>>; +extern template class Complex>; extern template class Complex, 113>>; } // namespace Fortran::evaluate::value #endif // FORTRAN_EVALUATE_COMPLEX_H_ diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h index b62e2bcb90f2f3326faf4377307b74500e187af3..10a13115a39e00c3c7522c02d2b635b6c5bfac6a 100644 --- a/flang/include/flang/Evaluate/integer.h +++ b/flang/include/flang/Evaluate/integer.h @@ -50,9 +50,12 @@ namespace Fortran::evaluate::value { // named accordingly in ALL CAPS so that they can be referenced easily in // the language standard. template , - typename BIGPART = HostUnsignedInt> + typename BIGPART = HostUnsignedInt, int ALIGNMENT = BITS> class Integer { public: static constexpr int bits{BITS}; @@ -79,6 +82,8 @@ private: static_assert((parts - 1) * partBits + topPartBits == bits); static constexpr Part partMask{static_cast(~0) >> extraPartBits}; static constexpr Part topPartMask{static_cast(~0) >> extraTopPartBits}; + static constexpr int partsWithAlignment{ + (ALIGNMENT + partBits - 1) / partBits}; public: // Some types used for member function results @@ -1043,14 +1048,16 @@ private: } } - Part part_[parts]{}; + Part part_[partsWithAlignment]{}; }; extern template class Integer<8>; extern template class Integer<16>; extern template class Integer<32>; extern template class Integer<64>; -extern template class Integer<80>; +using X87IntegerContainer = + Integer<80, true, 16, std::uint16_t, std::uint32_t, 128>; +extern template class Integer<80, true, 16, std::uint16_t, std::uint32_t, 128>; extern template class Integer<128>; } // namespace Fortran::evaluate::value #endif // FORTRAN_EVALUATE_INTEGER_H_ diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 6f2466c9da6773be811a4e34a6c36da3eda5d3c7..cb3c0036e0cfae1492e82177f1fd38a7687edd77 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -35,20 +35,19 @@ static constexpr std::int64_t ScaledLogBaseTenOfTwo{301029995664}; // class template must be (or look like) an instance of Integer<>; // the second specifies the number of effective bits (binary precision) // in the fraction. -template -class Real : public common::RealDetails { +template class Real { public: using Word = WORD; static constexpr int binaryPrecision{PREC}; - using Details = common::RealDetails; - using Details::exponentBias; - using Details::exponentBits; - using Details::isImplicitMSB; - using Details::maxExponent; - using Details::significandBits; + static constexpr common::RealCharacteristics realChars{PREC}; + static constexpr int exponentBias{realChars.exponentBias}; + static constexpr int exponentBits{realChars.exponentBits}; + static constexpr int isImplicitMSB{realChars.isImplicitMSB}; + static constexpr int maxExponent{realChars.maxExponent}; + static constexpr int significandBits{realChars.significandBits}; static constexpr int bits{Word::bits}; - static_assert(bits >= Details::bits); + static_assert(bits >= realChars.bits); using Fraction = Integer; // all bits made explicit template friend class Real; @@ -205,8 +204,8 @@ public: } static constexpr int DIGITS{binaryPrecision}; - static constexpr int PRECISION{Details::decimalPrecision}; - static constexpr int RANGE{Details::decimalRange}; + static constexpr int PRECISION{realChars.decimalPrecision}; + static constexpr int RANGE{realChars.decimalRange}; static constexpr int MAXEXPONENT{maxExponent - exponentBias}; static constexpr int MINEXPONENT{2 - exponentBias}; Real RRSPACING() const; @@ -371,6 +370,10 @@ public: return result; } bool isNegative{x.IsNegative()}; + if (x.IsInfinite()) { + result.value = Infinity(isNegative); + return result; + } A absX{x}; if (isNegative) { absX = x.Negate(); @@ -493,7 +496,7 @@ extern template class Real, 11>; // IEEE half format extern template class Real, 8>; // the "other" half format extern template class Real, 24>; // IEEE single extern template class Real, 53>; // IEEE double -extern template class Real, 64>; // 80387 extended precision +extern template class Real; // 80387 extended precision extern template class Real, 113>; // IEEE quad // N.B. No "double-double" support. } // namespace Fortran::evaluate::value diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h index da6efea6f8a742d14086595cb847a64a7f5eb3f4..93a0f21fa914557e1352aa4427dfa2558d220578 100644 --- a/flang/include/flang/Evaluate/type.h +++ b/flang/include/flang/Evaluate/type.h @@ -296,7 +296,10 @@ class Type public: static constexpr int precision{common::PrecisionOfRealKind(KIND)}; static constexpr int bits{common::BitsForBinaryPrecision(precision)}; - using Scalar = value::Real, precision>; + using Scalar = + value::Real>, + precision>; }; // The KIND type parameter on COMPLEX is the kind of each of its components. diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index d8840d9e967b48c25f34ded21b33508fae2b75a9..402a7a3f875299f0b7d1af447b97ace14a70730d 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -31,8 +31,7 @@ namespace fir { // Passes defined in Passes.td //===----------------------------------------------------------------------===// -#define GEN_PASS_DECL_ABSTRACTRESULTONFUNCOPT -#define GEN_PASS_DECL_ABSTRACTRESULTONGLOBALOPT +#define GEN_PASS_DECL_ABSTRACTRESULTOPT #define GEN_PASS_DECL_AFFINEDIALECTPROMOTION #define GEN_PASS_DECL_AFFINEDIALECTDEMOTION #define GEN_PASS_DECL_ANNOTATECONSTANTOPERANDS @@ -48,10 +47,9 @@ namespace fir { #define GEN_PASS_DECL_ALGEBRAICSIMPLIFICATION #define GEN_PASS_DECL_POLYMORPHICOPCONVERSION #define GEN_PASS_DECL_OPENACCDATAOPERANDCONVERSION +#define GEN_PASS_DECL_ADDDEBUGINFO #include "flang/Optimizer/Transforms/Passes.h.inc" -std::unique_ptr createAbstractResultOnFuncOptPass(); -std::unique_ptr createAbstractResultOnGlobalOptPass(); std::unique_ptr createAffineDemotionPass(); std::unique_ptr createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {}); @@ -67,7 +65,8 @@ std::unique_ptr createMemoryAllocationPass(); std::unique_ptr createStackArraysPass(); std::unique_ptr createAliasTagsPass(); std::unique_ptr createSimplifyIntrinsicsPass(); -std::unique_ptr createAddDebugInfoPass(); +std::unique_ptr +createAddDebugInfoPass(fir::AddDebugInfoOptions options = {}); std::unique_ptr createLoopVersioningPass(); std::unique_ptr diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index bfc0db8124af21cd42e42c5b6539c2892fecc5b8..c0b32459a935069c15aa271eaed26c232ccf3cc1 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -16,8 +16,8 @@ include "mlir/Pass/PassBase.td" -class AbstractResultOptBase - : Pass<"abstract-result-on-" # optExt # "-opt", operation> { +def AbstractResultOpt + : Pass<"abstract-result"> { let summary = "Convert fir.array, fir.box and fir.rec function result to " "function argument"; let description = [{ @@ -35,14 +35,6 @@ class AbstractResultOptBase ]; } -def AbstractResultOnFuncOpt : AbstractResultOptBase<"func", "mlir::func::FuncOp"> { - let constructor = "::fir::createAbstractResultOnFuncOptPass()"; -} - -def AbstractResultOnGlobalOpt : AbstractResultOptBase<"global", "fir::GlobalOp"> { - let constructor = "::fir::createAbstractResultOnGlobalOptPass()"; -} - def AffineDialectPromotion : Pass<"promote-to-affine", "::mlir::func::FuncOp"> { let summary = "Promotes `fir.{do_loop,if}` to `affine.{for,if}`."; let description = [{ @@ -210,6 +202,25 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> { let dependentDialects = [ "fir::FIROpsDialect", "mlir::func::FuncDialect", "mlir::LLVM::LLVMDialect" ]; + let options = [ + Option<"debugLevel", "debug-level", + "mlir::LLVM::DIEmissionKind", + /*default=*/"mlir::LLVM::DIEmissionKind::Full", + "debug level", + [{::llvm::cl::values( + clEnumValN(mlir::LLVM::DIEmissionKind::Full, "Full", "Emit full debug info"), + clEnumValN(mlir::LLVM::DIEmissionKind::LineTablesOnly, "LineTablesOnly", "Emit line tables only"), + clEnumValN(mlir::LLVM::DIEmissionKind::None, "None", "Emit no debug information") + )}] + >, + Option<"isOptimized", "is-optimized", + "bool", /*default=*/"false", + "is optimized.">, + Option<"inputFilename", "file-name", + "std::string", + /*default=*/"std::string{}", + "name of the input source file">, + ]; } // This needs to be a "mlir::ModuleOp" pass, because it inserts simplified diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 67153ffb3be9f6eac7440cff37214427c87ebbcc..4d0a993d02752cb5f6c707abc0e0e240ef351755 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -435,12 +435,17 @@ public: void set_init(std::nullptr_t) { init_ = nullptr; } bool isCUDAKernel() const { return isCUDAKernel_; } void set_isCUDAKernel(bool yes = true) { isCUDAKernel_ = yes; } + std::optional usedAsProcedureHere() const { + return usedAsProcedureHere_; + } + void set_usedAsProcedureHere(SourceName here) { usedAsProcedureHere_ = here; } private: const Symbol *rawProcInterface_{nullptr}; const Symbol *procInterface_{nullptr}; std::optional init_; bool isCUDAKernel_{false}; + std::optional usedAsProcedureHere_; friend llvm::raw_ostream &operator<<( llvm::raw_ostream &, const ProcEntityDetails &); }; diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index ea297fb337a2c84f86680d79510806f2eff60ea3..f02c969ca1c314997757b8e059871a08f8e5ab83 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -19,6 +19,7 @@ #include "flang/Optimizer/Transforms/Passes.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CommandLine.h" +#include #define DisableOption(DOName, DOOption, DODescription) \ static llvm::cl::opt disable##DOName("disable-" DOOption, \ @@ -86,6 +87,29 @@ DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite", DisableOption(ExternalNameConversion, "external-name-interop", "convert names with external convention"); +// TODO: remove once these are used for non-codegen passes +#if !defined(FLANG_EXCLUDE_CODEGEN) +using PassConstructor = std::unique_ptr(); + +template +void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) { + pm.addNestedPass(ctor()); +} + +template > +void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) { + addNestedPassToOps(pm, ctor); + addNestedPassToOps(pm, ctor); +} + +void addNestedPassToAllTopLevelOperations( + mlir::PassManager &pm, PassConstructor ctor) { + addNestedPassToOps(pm, ctor); +} +#endif + /// Generic for adding a pass to the pass manager if it is not disabled. template void addPassConditionally( @@ -155,9 +179,27 @@ inline void addTargetRewritePass(mlir::PassManager &pm) { }); } -inline void addDebugInfoPass(mlir::PassManager &pm) { - addPassConditionally( - pm, disableDebugInfo, [&]() { return fir::createAddDebugInfoPass(); }); +inline mlir::LLVM::DIEmissionKind getEmissionKind( + llvm::codegenoptions::DebugInfoKind kind) { + switch (kind) { + case llvm::codegenoptions::DebugInfoKind::FullDebugInfo: + return mlir::LLVM::DIEmissionKind::Full; + case llvm::codegenoptions::DebugInfoKind::DebugLineTablesOnly: + return mlir::LLVM::DIEmissionKind::LineTablesOnly; + default: + return mlir::LLVM::DIEmissionKind::None; + } +} + +inline void addDebugInfoPass(mlir::PassManager &pm, + llvm::codegenoptions::DebugInfoKind debugLevel, + llvm::OptimizationLevel optLevel, llvm::StringRef inputFilename) { + fir::AddDebugInfoOptions options; + options.debugLevel = getEmissionKind(debugLevel); + options.isOptimized = optLevel != llvm::OptimizationLevel::O0; + options.inputFilename = inputFilename; + addPassConditionally(pm, disableDebugInfo, + [&]() { return fir::createAddDebugInfoPass(options); }); } inline void addFIRToLLVMPass( @@ -283,34 +325,21 @@ inline void createOpenMPFIRPassPipeline( } #if !defined(FLANG_EXCLUDE_CODEGEN) -inline void createDebugPasses( - mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel) { - // Currently only -g1, -g, -gline-tables-only supported - switch (debugLevel) { - case llvm::codegenoptions::DebugLineTablesOnly: - addDebugInfoPass(pm); - return; - case llvm::codegenoptions::NoDebugInfo: - return; - default: - // TODO: Add cases and passes for other debug options. - // All other debug options not implemented yet, currently emits warning - // and generates as much debug information as possible. - addDebugInfoPass(pm); - return; - } +inline void createDebugPasses(mlir::PassManager &pm, + llvm::codegenoptions::DebugInfoKind debugLevel, + llvm::OptimizationLevel OptLevel, llvm::StringRef inputFilename) { + if (debugLevel != llvm::codegenoptions::NoDebugInfo) + addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename); } -inline void createDefaultFIRCodeGenPassPipeline( - mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config) { +inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, + MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename = {}) { fir::addBoxedProcedurePass(pm); - pm.addNestedPass( - fir::createAbstractResultOnFuncOptPass()); - pm.addNestedPass(fir::createAbstractResultOnGlobalOptPass()); + addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt); fir::addCodeGenRewritePass(pm); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm, config.Underscoring); - fir::createDebugPasses(pm, config.DebugInfo); + fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename); if (config.VScaleMin != 0) pm.addPass(fir::createVScaleAttrPass({config.VScaleMin, config.VScaleMax})); @@ -344,15 +373,16 @@ inline void createDefaultFIRCodeGenPassPipeline( /// \param pm - MLIR pass manager that will hold the pipeline definition /// \param optLevel - optimization level used for creating FIR optimization /// passes pipeline -inline void createMLIRToLLVMPassPipeline( - mlir::PassManager &pm, const MLIRToLLVMPassPipelineConfig &config) { +inline void createMLIRToLLVMPassPipeline(mlir::PassManager &pm, + const MLIRToLLVMPassPipelineConfig &config, + llvm::StringRef inputFilename = {}) { fir::createHLFIRToFIRPassPipeline(pm, config.OptLevel); // Add default optimizer pass pipeline. fir::createDefaultFIROptimizerPassPipeline(pm, config); // Add codegen pass pipeline. - fir::createDefaultFIRCodeGenPassPipeline(pm, config); + fir::createDefaultFIRCodeGenPassPipeline(pm, config, inputFilename); } #undef FLANG_EXCLUDE_CODEGEN #endif diff --git a/flang/lib/Decimal/big-radix-floating-point.h b/flang/lib/Decimal/big-radix-floating-point.h index 6ce8ae7925c150911a7e42098f994dd23de553a8..f9afebf5b3d703e44ed8d1e5ae313ba2a0de5d52 100644 --- a/flang/lib/Decimal/big-radix-floating-point.h +++ b/flang/lib/Decimal/big-radix-floating-point.h @@ -83,6 +83,8 @@ public: return *this; } + RT_API_ATTRS bool IsInteger() const { return exponent_ >= 0; } + // Converts decimal floating-point to binary. RT_API_ATTRS ConversionToBinaryResult ConvertToBinary(); diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp index 688a856220a117c2026e9df855e24ec0abb1b02d..20f7476425ace616e8fa06afa0c1d9a2019bc231 100644 --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -576,11 +576,11 @@ static std::optional CharacterizeDummyArgument( semantics::UnorderedSymbolSet seenProcs); static std::optional CharacterizeFunctionResult( const semantics::Symbol &symbol, FoldingContext &context, - semantics::UnorderedSymbolSet seenProcs); + semantics::UnorderedSymbolSet seenProcs, bool emitError); static std::optional CharacterizeProcedure( const semantics::Symbol &original, FoldingContext &context, - semantics::UnorderedSymbolSet seenProcs) { + semantics::UnorderedSymbolSet seenProcs, bool emitError) { const auto &symbol{ResolveAssociations(original)}; if (seenProcs.find(symbol) != seenProcs.end()) { std::string procsList{GetSeenProcs(seenProcs)}; @@ -591,6 +591,13 @@ static std::optional CharacterizeProcedure( return std::nullopt; } seenProcs.insert(symbol); + auto CheckForNested{[&](const Symbol &symbol) { + if (emitError) { + context.messages().Say( + "Procedure '%s' is referenced before being sufficiently defined in a context where it must be so"_err_en_US, + symbol.name()); + } + }}; auto result{common::visit( common::visitors{ [&](const semantics::SubprogramDetails &subp) @@ -598,7 +605,7 @@ static std::optional CharacterizeProcedure( Procedure result; if (subp.isFunction()) { if (auto fr{CharacterizeFunctionResult( - subp.result(), context, seenProcs)}) { + subp.result(), context, seenProcs, emitError)}) { result.functionResult = std::move(fr); } else { return std::nullopt; @@ -641,8 +648,8 @@ static std::optional CharacterizeProcedure( } if (const semantics::Symbol * interfaceSymbol{proc.procInterface()}) { - auto result{ - CharacterizeProcedure(*interfaceSymbol, context, seenProcs)}; + auto result{CharacterizeProcedure( + *interfaceSymbol, context, seenProcs, /*emitError=*/false)}; if (result && (IsDummy(symbol) || IsPointer(symbol))) { // Dummy procedures and procedure pointers may not be // ELEMENTAL, but we do accept the use of elemental intrinsic @@ -675,8 +682,8 @@ static std::optional CharacterizeProcedure( } }, [&](const semantics::ProcBindingDetails &binding) { - if (auto result{CharacterizeProcedure( - binding.symbol(), context, seenProcs)}) { + if (auto result{CharacterizeProcedure(binding.symbol(), context, + seenProcs, /*emitError=*/false)}) { if (binding.symbol().attrs().test(semantics::Attr::INTRINSIC)) { result->attrs.reset(Procedure::Attr::Elemental); } @@ -695,7 +702,8 @@ static std::optional CharacterizeProcedure( } }, [&](const semantics::UseDetails &use) { - return CharacterizeProcedure(use.symbol(), context, seenProcs); + return CharacterizeProcedure( + use.symbol(), context, seenProcs, /*emitError=*/false); }, [](const semantics::UseErrorDetails &) { // Ambiguous use-association will be handled later during symbol @@ -703,25 +711,23 @@ static std::optional CharacterizeProcedure( return std::optional{}; }, [&](const semantics::HostAssocDetails &assoc) { - return CharacterizeProcedure(assoc.symbol(), context, seenProcs); + return CharacterizeProcedure( + assoc.symbol(), context, seenProcs, /*emitError=*/false); }, [&](const semantics::GenericDetails &generic) { if (const semantics::Symbol * specific{generic.specific()}) { - return CharacterizeProcedure(*specific, context, seenProcs); + return CharacterizeProcedure( + *specific, context, seenProcs, emitError); } else { return std::optional{}; } }, [&](const semantics::EntityDetails &) { - context.messages().Say( - "Procedure '%s' is referenced before being sufficiently defined in a context where it must be so"_err_en_US, - symbol.name()); + CheckForNested(symbol); return std::optional{}; }, [&](const semantics::SubprogramNameDetails &) { - context.messages().Say( - "Procedure '%s' is referenced before being sufficiently defined in a context where it must be so"_err_en_US, - symbol.name()); + CheckForNested(symbol); return std::optional{}; }, [&](const auto &) { @@ -752,7 +758,8 @@ static std::optional CharacterizeProcedure( static std::optional CharacterizeDummyProcedure( const semantics::Symbol &symbol, FoldingContext &context, semantics::UnorderedSymbolSet seenProcs) { - if (auto procedure{CharacterizeProcedure(symbol, context, seenProcs)}) { + if (auto procedure{CharacterizeProcedure( + symbol, context, seenProcs, /*emitError=*/true)}) { // Dummy procedures may not be elemental. Elemental dummy procedure // interfaces are errors when the interface is not intrinsic, and that // error is caught elsewhere. Elemental intrinsic interfaces are @@ -854,7 +861,8 @@ std::optional DummyArgument::FromActual(std::string &&name, std::move(name), std::move(obj)); }, [&](const ProcedureDesignator &designator) { - if (auto proc{Procedure::Characterize(designator, context)}) { + if (auto proc{Procedure::Characterize( + designator, context, /*emitError=*/true)}) { return std::make_optional( std::move(name), DummyProcedure{std::move(*proc)}); } else { @@ -988,7 +996,7 @@ bool FunctionResult::operator==(const FunctionResult &that) const { static std::optional CharacterizeFunctionResult( const semantics::Symbol &symbol, FoldingContext &context, - semantics::UnorderedSymbolSet seenProcs) { + semantics::UnorderedSymbolSet seenProcs, bool emitError) { if (const auto *object{symbol.detailsIf()}) { if (auto type{TypeAndShape::Characterize( symbol, context, /*invariantOnly=*/false)}) { @@ -1002,8 +1010,8 @@ static std::optional CharacterizeFunctionResult( result.cudaDataAttr = object->cudaDataAttr(); return result; } - } else if (auto maybeProc{ - CharacterizeProcedure(symbol, context, seenProcs)}) { + } else if (auto maybeProc{CharacterizeProcedure( + symbol, context, seenProcs, emitError)}) { FunctionResult result{std::move(*maybeProc)}; result.attrs.set(FunctionResult::Attr::Pointer); return result; @@ -1014,7 +1022,8 @@ static std::optional CharacterizeFunctionResult( std::optional FunctionResult::Characterize( const Symbol &symbol, FoldingContext &context) { semantics::UnorderedSymbolSet seenProcs; - return CharacterizeFunctionResult(symbol, context, seenProcs); + return CharacterizeFunctionResult( + symbol, context, seenProcs, /*emitError=*/false); } bool FunctionResult::IsAssumedLengthCharacter() const { @@ -1360,27 +1369,26 @@ bool Procedure::CanOverride( } std::optional Procedure::Characterize( - const semantics::Symbol &original, FoldingContext &context) { + const semantics::Symbol &symbol, FoldingContext &context) { semantics::UnorderedSymbolSet seenProcs; - return CharacterizeProcedure(original, context, seenProcs); + return CharacterizeProcedure(symbol, context, seenProcs, /*emitError=*/true); } std::optional Procedure::Characterize( - const ProcedureDesignator &proc, FoldingContext &context) { + const ProcedureDesignator &proc, FoldingContext &context, bool emitError) { if (const auto *symbol{proc.GetSymbol()}) { - if (auto result{ - characteristics::Procedure::Characterize(*symbol, context)}) { - return result; - } + semantics::UnorderedSymbolSet seenProcs; + return CharacterizeProcedure(*symbol, context, seenProcs, emitError); } else if (const auto *intrinsic{proc.GetSpecificIntrinsic()}) { return intrinsic->characteristics.value(); + } else { + return std::nullopt; } - return std::nullopt; } std::optional Procedure::Characterize( const ProcedureRef &ref, FoldingContext &context) { - if (auto callee{Characterize(ref.proc(), context)}) { + if (auto callee{Characterize(ref.proc(), context, /*emitError=*/true)}) { if (callee->functionResult) { if (const Procedure * proc{callee->functionResult->IsProcedurePointer()}) { @@ -1397,7 +1405,7 @@ std::optional Procedure::Characterize( return Characterize(*procRef, context); } else if (const auto *procDesignator{ std::get_if(&expr.u)}) { - return Characterize(*procDesignator, context); + return Characterize(*procDesignator, context, /*emitError=*/true); } else if (const Symbol * symbol{UnwrapWholeSymbolOrComponentDataRef(expr)}) { return Characterize(*symbol, context); } else { @@ -1409,7 +1417,7 @@ std::optional Procedure::Characterize( std::optional Procedure::FromActuals(const ProcedureDesignator &proc, const ActualArguments &args, FoldingContext &context) { - auto callee{Characterize(proc, context)}; + auto callee{Characterize(proc, context, /*emitError=*/true)}; if (callee) { if (callee->dummyArguments.empty() && callee->attrs.test(Procedure::Attr::ImplicitInterface)) { diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 0e14aa0957294c799f4627eddf5be5e058829033..7e42db7b6ed7ab0bdaa807a94c37ce11a141e7f8 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -666,8 +666,8 @@ public: "' not allowed for derived type components or type parameter" " values"; } - if (auto procChars{ - characteristics::Procedure::Characterize(x.proc(), context_)}) { + if (auto procChars{characteristics::Procedure::Characterize( + x.proc(), context_, /*emitError=*/true)}) { const auto iter{std::find_if(procChars->dummyArguments.begin(), procChars->dummyArguments.end(), [](const characteristics::DummyArgument &dummy) { @@ -856,8 +856,8 @@ public: Result operator()(const Substring &) const { return std::nullopt; } Result operator()(const ProcedureRef &x) const { - if (auto chars{ - characteristics::Procedure::Characterize(x.proc(), context_)}) { + if (auto chars{characteristics::Procedure::Characterize( + x.proc(), context_, /*emitError=*/true)}) { if (chars->functionResult) { const auto &result{*chars->functionResult}; if (!result.IsProcedurePointer()) { @@ -1103,8 +1103,8 @@ public: } } } - if (auto chars{ - characteristics::Procedure::Characterize(proc, context_)}) { + if (auto chars{characteristics::Procedure::Characterize( + proc, context_, /*emitError=*/true)}) { if (!chars->CanBeCalledViaImplicitInterface()) { if (severity_) { auto msg{ diff --git a/flang/lib/Evaluate/complex.cpp b/flang/lib/Evaluate/complex.cpp index e683d7e0229ca5b7f7f2ca4126dc700086bca908..ab83f193e3f3e1a6a18e059f7fb8710c9d5e3ee2 100644 --- a/flang/lib/Evaluate/complex.cpp +++ b/flang/lib/Evaluate/complex.cpp @@ -120,6 +120,6 @@ template class Complex, 11>>; template class Complex, 8>>; template class Complex, 24>>; template class Complex, 53>>; -template class Complex, 64>>; +template class Complex>; template class Complex, 113>>; } // namespace Fortran::evaluate::value diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 34f79f9e6f25b489c9d2e0959ef3df2b6648d8f6..093f26bea1a44f8ed6977d5a6a79d52b0a91be8c 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -201,11 +201,12 @@ std::optional> Folder::ApplySubscripts(const Constant &array, ConstantSubscripts resultShape; ConstantSubscripts ssLB; for (const auto &ss : subscripts) { - CHECK(ss.Rank() <= 1); if (ss.Rank() == 1) { resultShape.push_back(static_cast(ss.size())); elements *= ss.size(); ssLB.push_back(ss.lbounds().front()); + } else if (ss.Rank() > 1) { + return std::nullopt; // error recovery } } ConstantSubscripts ssAt(rank, 0), at(rank, 0), tmp(1, 0); diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp index 5a9596f3c274b5af879f3a8eee21dcc4c399c552..b7d641711c363d90d3c9f99772a806083b293a46 100644 --- a/flang/lib/Evaluate/fold-logical.cpp +++ b/flang/lib/Evaluate/fold-logical.cpp @@ -41,6 +41,583 @@ static Expr FoldAllAnyParity(FoldingContext &context, FunctionRef &&ref, return Expr{std::move(ref)}; } +// OUT_OF_RANGE(x,mold[,round]) references are entirely rewritten here into +// expressions, which are then folded into constants when 'x' and 'round' +// are constant. It is guaranteed that 'x' is evaluated at most once. + +template +Expr RealToIntBoundHelper(bool round, bool negate) { + using RType = Type; + using RealType = Scalar; + using IntType = Scalar>; + RealType result{}; // 0. + common::RoundingMode roundingMode{round + ? common::RoundingMode::TiesAwayFromZero + : common::RoundingMode::ToZero}; + // Add decreasing powers of two to the result to find the largest magnitude + // value that can be converted to the integer type without overflow. + RealType at{RealType::FromInteger(IntType{negate ? -1 : 1}).value}; + bool decrement{true}; + while (!at.template ToInteger(roundingMode) + .flags.test(RealFlag::Overflow)) { + auto tmp{at.SCALE(IntType{1})}; + if (tmp.flags.test(RealFlag::Overflow)) { + decrement = false; + break; + } + at = tmp.value; + } + while (true) { + if (decrement) { + at = at.SCALE(IntType{-1}).value; + } else { + decrement = true; + } + auto tmp{at.Add(result)}; + if (tmp.flags.test(RealFlag::Inexact)) { + break; + } else if (!tmp.value.template ToInteger(roundingMode) + .flags.test(RealFlag::Overflow)) { + result = tmp.value; + } + } + return AsCategoryExpr(Constant{std::move(result)}); +} + +static Expr RealToIntBound( + int xRKind, int moldIKind, bool round, bool negate) { + switch (xRKind) { +#define ICASES(RK) \ + switch (moldIKind) { \ + case 1: \ + return RealToIntBoundHelper(round, negate); \ + break; \ + case 2: \ + return RealToIntBoundHelper(round, negate); \ + break; \ + case 4: \ + return RealToIntBoundHelper(round, negate); \ + break; \ + case 8: \ + return RealToIntBoundHelper(round, negate); \ + break; \ + case 16: \ + return RealToIntBoundHelper(round, negate); \ + break; \ + } \ + break + case 2: + ICASES(2); + break; + case 3: + ICASES(3); + break; + case 4: + ICASES(4); + break; + case 8: + ICASES(8); + break; + case 10: + ICASES(10); + break; + case 16: + ICASES(16); + break; + } + DIE("RealToIntBound: no case"); +#undef ICASES +} + +class RealToIntLimitHelper { +public: + using Result = std::optional>; + using Types = RealTypes; + RealToIntLimitHelper( + FoldingContext &context, Expr &&hi, Expr &lo) + : context_{context}, hi_{std::move(hi)}, lo_{lo} {} + template Result Test() { + if (UnwrapExpr>(hi_)) { + bool promote{T::kind < 16}; + Result constResult; + if (auto hiV{GetScalarConstantValue(hi_)}) { + auto loV{GetScalarConstantValue(lo_)}; + CHECK(loV.has_value()); + auto diff{hiV->Subtract(*loV, Rounding{common::RoundingMode::ToZero})}; + promote = promote && + (diff.flags.test(RealFlag::Overflow) || + diff.flags.test(RealFlag::Inexact)); + constResult = AsCategoryExpr(Constant{std::move(diff.value)}); + } + if (promote) { + constexpr int nextKind{T::kind < 4 ? 4 : T::kind == 4 ? 8 : 16}; + using T2 = Type; + hi_ = Expr{Fold(context_, ConvertToType(std::move(hi_)))}; + lo_ = Expr{Fold(context_, ConvertToType(std::move(lo_)))}; + if (constResult) { + // Use promoted constants on next iteration of SearchTypes + return std::nullopt; + } + } + if (constResult) { + return constResult; + } else { + return AsCategoryExpr(std::move(hi_) - Expr{lo_}); + } + } else { + return std::nullopt; + } + } + +private: + FoldingContext &context_; + Expr hi_; + Expr &lo_; +}; + +static std::optional> RealToIntLimit( + FoldingContext &context, Expr &&hi, Expr &lo) { + return common::SearchTypes(RealToIntLimitHelper{context, std::move(hi), lo}); +} + +// RealToRealBounds() returns a pair (HUGE(x),REAL(HUGE(mold),KIND(x))) +// when REAL(HUGE(x),KIND(mold)) overflows, and std::nullopt otherwise. +template +std::optional, Expr>> +RealToRealBoundsHelper() { + using RType = Type; + using RealType = Scalar; + using MoldRealType = Scalar>; + if (!MoldRealType::Convert(RealType::HUGE()).flags.test(RealFlag::Overflow)) { + return std::nullopt; + } else { + return std::make_pair(AsCategoryExpr(Constant{ + RealType::Convert(MoldRealType::HUGE()).value}), + AsCategoryExpr(Constant{RealType::HUGE()})); + } +} + +static std::optional, Expr>> +RealToRealBounds(int xRKind, int moldRKind) { + switch (xRKind) { +#define RCASES(RK) \ + switch (moldRKind) { \ + case 2: \ + return RealToRealBoundsHelper(); \ + break; \ + case 3: \ + return RealToRealBoundsHelper(); \ + break; \ + case 4: \ + return RealToRealBoundsHelper(); \ + break; \ + case 8: \ + return RealToRealBoundsHelper(); \ + break; \ + case 10: \ + return RealToRealBoundsHelper(); \ + break; \ + case 16: \ + return RealToRealBoundsHelper(); \ + break; \ + } \ + break + case 2: + RCASES(2); + break; + case 3: + RCASES(3); + break; + case 4: + RCASES(4); + break; + case 8: + RCASES(8); + break; + case 10: + RCASES(10); + break; + case 16: + RCASES(16); + break; + } + DIE("RealToRealBounds: no case"); +#undef RCASES +} + +template +std::optional> IntToRealBoundHelper(bool negate) { + using IType = Type; + using IntType = Scalar; + using RealType = Scalar>; + IntType result{}; // 0 + while (true) { + std::optional next; + for (int bit{0}; bit < IntType::bits; ++bit) { + IntType power{IntType{}.IBSET(bit)}; + if (power.IsNegative()) { + if (!negate) { + break; + } + } else if (negate) { + power = power.Negate().value; + } + auto tmp{power.AddSigned(result)}; + if (tmp.overflow || + RealType::FromInteger(tmp.value).flags.test(RealFlag::Overflow)) { + break; + } + next = tmp.value; + } + if (next) { + CHECK(result.CompareSigned(*next) != Ordering::Equal); + result = *next; + } else { + break; + } + } + if (result.CompareSigned(IntType::HUGE()) == Ordering::Equal) { + return std::nullopt; + } else { + return AsCategoryExpr(Constant{std::move(result)}); + } +} + +static std::optional> IntToRealBound( + int xIKind, int moldRKind, bool negate) { + switch (xIKind) { +#define RCASES(IK) \ + switch (moldRKind) { \ + case 2: \ + return IntToRealBoundHelper(negate); \ + break; \ + case 3: \ + return IntToRealBoundHelper(negate); \ + break; \ + case 4: \ + return IntToRealBoundHelper(negate); \ + break; \ + case 8: \ + return IntToRealBoundHelper(negate); \ + break; \ + case 10: \ + return IntToRealBoundHelper(negate); \ + break; \ + case 16: \ + return IntToRealBoundHelper(negate); \ + break; \ + } \ + break + case 1: + RCASES(1); + break; + case 2: + RCASES(2); + break; + case 4: + RCASES(4); + break; + case 8: + RCASES(8); + break; + case 16: + RCASES(16); + break; + } + DIE("IntToRealBound: no case"); +#undef RCASES +} + +template +std::optional> IntToIntBoundHelper() { + if constexpr (X_IKIND <= MOLD_IKIND) { + return std::nullopt; + } else { + using XIType = Type; + using IntegerType = Scalar; + using MoldIType = Type; + using MoldIntegerType = Scalar; + return AsCategoryExpr(Constant{ + IntegerType::ConvertSigned(MoldIntegerType::HUGE()).value}); + } +} + +static std::optional> IntToIntBound( + int xIKind, int moldIKind) { + switch (xIKind) { +#define ICASES(IK) \ + switch (moldIKind) { \ + case 1: \ + return IntToIntBoundHelper(); \ + break; \ + case 2: \ + return IntToIntBoundHelper(); \ + break; \ + case 4: \ + return IntToIntBoundHelper(); \ + break; \ + case 8: \ + return IntToIntBoundHelper(); \ + break; \ + case 16: \ + return IntToIntBoundHelper(); \ + break; \ + } \ + break + case 1: + ICASES(1); + break; + case 2: + ICASES(2); + break; + case 4: + ICASES(4); + break; + case 8: + ICASES(8); + break; + case 16: + ICASES(16); + break; + } + DIE("IntToIntBound: no case"); +#undef ICASES +} + +// ApplyIntrinsic() constructs the typed expression representation +// for a specific intrinsic function reference. +// TODO: maybe move into tools.h? +class IntrinsicCallHelper { +public: + explicit IntrinsicCallHelper(SpecificCall &&call) : call_{call} { + CHECK(proc_.IsFunction()); + typeAndShape_ = proc_.functionResult->GetTypeAndShape(); + CHECK(typeAndShape_ != nullptr); + } + using Result = std::optional>; + using Types = LengthlessIntrinsicTypes; + template Result Test() { + if (T::category == typeAndShape_->type().category() && + T::kind == typeAndShape_->type().kind()) { + return AsGenericExpr(FunctionRef{ + ProcedureDesignator{std::move(call_.specificIntrinsic)}, + std::move(call_.arguments)}); + } else { + return std::nullopt; + } + } + +private: + SpecificCall call_; + const characteristics::Procedure &proc_{ + call_.specificIntrinsic.characteristics.value()}; + const characteristics::TypeAndShape *typeAndShape_{nullptr}; +}; + +static Expr ApplyIntrinsic( + FoldingContext &context, const std::string &func, ActualArguments &&args) { + auto found{ + context.intrinsics().Probe(CallCharacteristics{func}, args, context)}; + CHECK(found.has_value()); + auto result{common::SearchTypes(IntrinsicCallHelper{std::move(*found)})}; + CHECK(result.has_value()); + return *result; +} + +static Expr CompareUnsigned(FoldingContext &context, + const char *intrin, Expr &&x, Expr &&y) { + Expr result{ApplyIntrinsic(context, intrin, + ActualArguments{ + ActualArgument{std::move(x)}, ActualArgument{std::move(y)}})}; + return DEREF(UnwrapExpr>(result)); +} + +// Determines the right kind of INTEGER to hold the bits of a REAL type. +static Expr IntTransferMold( + const TargetCharacteristics &target, DynamicType realType, bool asVector) { + CHECK(realType.category() == TypeCategory::Real); + int rKind{realType.kind()}; + int iKind{std::max(target.GetAlignment(TypeCategory::Real, rKind), + target.GetByteSize(TypeCategory::Real, rKind))}; + CHECK(target.CanSupportType(TypeCategory::Integer, iKind)); + DynamicType iType{TypeCategory::Integer, iKind}; + ConstantSubscripts shape; + if (asVector) { + shape = ConstantSubscripts{1}; + } + Constant value{ + std::vector>{0}, std::move(shape)}; + auto expr{ConvertToType(iType, AsGenericExpr(std::move(value)))}; + CHECK(expr.has_value()); + return std::move(*expr); +} + +static Expr GetRealBits(FoldingContext &context, Expr &&x) { + auto xType{x.GetType()}; + CHECK(xType.has_value()); + bool asVector{x.Rank() > 0}; + return ApplyIntrinsic(context, "transfer", + ActualArguments{ActualArgument{AsGenericExpr(std::move(x))}, + ActualArgument{IntTransferMold( + context.targetCharacteristics(), *xType, asVector)}}); +} + +template +static Expr> RewriteOutOfRange( + FoldingContext &context, + FunctionRef> &&funcRef) { + using ResultType = Type; + ActualArguments &args{funcRef.arguments()}; + // Fold x= and round= unconditionally + if (auto *x{UnwrapExpr>(args[0])}) { + *args[0] = Fold(context, std::move(*x)); + } + if (args.size() >= 3) { + if (auto *round{UnwrapExpr>(args[2])}) { + *args[2] = Fold(context, std::move(*round)); + } + } + if (auto *x{UnwrapExpr>(args[0])}) { + x = UnwrapExpr>(args[0]); + CHECK(x != nullptr); + if (const auto *mold{UnwrapExpr>(args[1])}) { + DynamicType xType{x->GetType().value()}; + std::optional> result; + bool alwaysFalse{false}; + if (auto *iXExpr{UnwrapExpr>(*x)}) { + int iXKind{iXExpr->GetType().value().kind()}; + if (auto *iMoldExpr{UnwrapExpr>(*mold)}) { + // INTEGER -> INTEGER + int iMoldKind{iMoldExpr->GetType().value().kind()}; + if (auto hi{IntToIntBound(iXKind, iMoldKind)}) { + // 'hi' is INT(HUGE(mold), KIND(x)) + // OUT_OF_RANGE(x,mold) = (x + (hi + 1)) .UGT. (2*hi + 1) + auto one{DEREF(UnwrapExpr>(ConvertToType( + xType, AsGenericExpr(Constant{1}))))}; + auto lhs{std::move(*iXExpr) + + (Expr{*hi} + Expr{one})}; + auto two{DEREF(UnwrapExpr>(ConvertToType( + xType, AsGenericExpr(Constant{2}))))}; + auto rhs{std::move(two) * std::move(*hi) + std::move(one)}; + result = CompareUnsigned(context, "bgt", + Expr{std::move(lhs)}, Expr{std::move(rhs)}); + } else { + alwaysFalse = true; + } + } else if (auto *rMoldExpr{UnwrapExpr>(*mold)}) { + // INTEGER -> REAL + int rMoldKind{rMoldExpr->GetType().value().kind()}; + if (auto hi{IntToRealBound(iXKind, rMoldKind, /*negate=*/false)}) { + // OUT_OF_RANGE(x,mold) = (x - lo) .UGT. (hi - lo) + auto lo{IntToRealBound(iXKind, rMoldKind, /*negate=*/true)}; + CHECK(lo.has_value()); + auto lhs{std::move(*iXExpr) - Expr{*lo}}; + auto rhs{std::move(*hi) - std::move(*lo)}; + result = CompareUnsigned(context, "bgt", + Expr{std::move(lhs)}, Expr{std::move(rhs)}); + } else { + alwaysFalse = true; + } + } + } else if (auto *rXExpr{UnwrapExpr>(*x)}) { + int rXKind{rXExpr->GetType().value().kind()}; + if (auto *iMoldExpr{UnwrapExpr>(*mold)}) { + // REAL -> INTEGER + int iMoldKind{iMoldExpr->GetType().value().kind()}; + auto hi{RealToIntBound(rXKind, iMoldKind, false, false)}; + auto lo{RealToIntBound(rXKind, iMoldKind, false, true)}; + if (args.size() >= 3) { + // Bounds depend on round= value + if (auto *round{UnwrapExpr>(args[2])}) { + if (const Symbol * whole{UnwrapWholeSymbolDataRef(*round)}; + whole && semantics::IsOptional(whole->GetUltimate())) { + if (auto source{args[2]->sourceLocation()}) { + context.messages().Say(*source, + "ROUND= argument to OUT_OF_RANGE() is an optional dummy argument that must be present at execution"_warn_en_US); + } + } + auto rlo{RealToIntBound(rXKind, iMoldKind, true, true)}; + auto rhi{RealToIntBound(rXKind, iMoldKind, true, false)}; + auto mlo{Fold(context, + ApplyIntrinsic(context, "merge", + ActualArguments{ + ActualArgument{Expr{std::move(rlo)}}, + ActualArgument{Expr{std::move(lo)}}, + ActualArgument{Expr{*round}}}))}; + auto mhi{Fold(context, + ApplyIntrinsic(context, "merge", + ActualArguments{ + ActualArgument{Expr{std::move(rhi)}}, + ActualArgument{Expr{std::move(hi)}}, + ActualArgument{std::move(*round)}}))}; + lo = std::move(DEREF(UnwrapExpr>(mlo))); + hi = std::move(DEREF(UnwrapExpr>(mhi))); + } + } + // OUT_OF_RANGE(x,mold[,round]) = + // TRANSFER(x - lo, int) .UGT. TRANSFER(hi - lo, int) + hi = Fold(context, std::move(hi)); + lo = Fold(context, std::move(lo)); + if (auto rhs{RealToIntLimit(context, std::move(hi), lo)}) { + Expr lhs{std::move(*rXExpr) - std::move(lo)}; + result = CompareUnsigned(context, "bgt", + GetRealBits(context, std::move(lhs)), + GetRealBits(context, std::move(*rhs))); + } + } else if (auto *rMoldExpr{UnwrapExpr>(*mold)}) { + // REAL -> REAL + // Only finite arguments with ABS(x) > HUGE(mold) are .TRUE. + // OUT_OF_RANGE(x,mold) = + // TRANSFER(ABS(x) - HUGE(mold), int) - 1 .ULT. + // TRANSFER(HUGE(mold), int) + // Note that OUT_OF_RANGE(+/-Inf or NaN,mold) = + // TRANSFER(+Inf or Nan, int) - 1 .ULT. TRANSFER(HUGE(mold), int) + int rMoldKind{rMoldExpr->GetType().value().kind()}; + if (auto bounds{RealToRealBounds(rXKind, rMoldKind)}) { + auto &[moldHuge, xHuge]{*bounds}; + Expr abs{ApplyIntrinsic(context, "abs", + ActualArguments{ + ActualArgument{Expr{std::move(*rXExpr)}}})}; + auto &absR{DEREF(UnwrapExpr>(abs))}; + Expr diffBits{ + GetRealBits(context, std::move(absR) - std::move(moldHuge))}; + auto &diffBitsI{DEREF(UnwrapExpr>(diffBits))}; + Expr decr{std::move(diffBitsI) - + Expr{Expr{1}}}; + result = CompareUnsigned(context, "blt", std::move(decr), + GetRealBits(context, std::move(xHuge))); + } else { + alwaysFalse = true; + } + } + } + if (alwaysFalse) { + // xType can never overflow moldType, so + // OUT_OF_RANGE(x) = (x /= 0) .AND. .FALSE. + // which has the same shape as x. + Expr scalarFalse{ + Constant{Scalar{false}}}; + if (x->Rank() > 0) { + if (auto nez{Relate(context.messages(), RelationalOperator::NE, + std::move(*x), + AsGenericExpr(Constant{0}))}) { + result = Expr{LogicalOperation{ + LogicalOperator::And, std::move(*nez), std::move(scalarFalse)}}; + } + } else { + result = std::move(scalarFalse); + } + } + if (result) { + auto restorer{context.messages().DiscardMessages()}; + return Fold( + context, AsExpr(ConvertToType(std::move(*result)))); + } + } + } + return AsExpr(std::move(funcRef)); +} + template Expr> FoldIntrinsicFunction( FoldingContext &context, @@ -236,114 +813,7 @@ Expr> FoldIntrinsicFunction( } else if (name == "matmul") { return FoldMatmul(context, std::move(funcRef)); } else if (name == "out_of_range") { - if (Expr * cx{UnwrapExpr>(args[0])}) { - auto restorer{context.messages().DiscardMessages()}; - *args[0] = Fold(context, std::move(*cx)); - if (Expr & folded{DEREF(args[0].value().UnwrapExpr())}; - IsActuallyConstant(folded)) { - std::optional> result; - if (Expr * realMold{UnwrapExpr>(args[1])}) { - if (const auto *xInt{UnwrapExpr>(folded)}) { - result.emplace(); - std::visit( - [&](const auto &mold, const auto &x) { - using RealType = - typename std::decay_t::Result; - static_assert(RealType::category == TypeCategory::Real); - using Scalar = typename RealType::Scalar; - using xType = typename std::decay_t::Result; - const auto &xConst{DEREF(UnwrapExpr>(x))}; - for (const auto &elt : xConst.values()) { - result->emplace_back( - Scalar::template FromInteger(elt).flags.test( - RealFlag::Overflow)); - } - }, - realMold->u, xInt->u); - } else if (const auto *xReal{UnwrapExpr>(folded)}) { - result.emplace(); - std::visit( - [&](const auto &mold, const auto &x) { - using RealType = - typename std::decay_t::Result; - static_assert(RealType::category == TypeCategory::Real); - using Scalar = typename RealType::Scalar; - using xType = typename std::decay_t::Result; - const auto &xConst{DEREF(UnwrapExpr>(x))}; - for (const auto &elt : xConst.values()) { - result->emplace_back(elt.IsFinite() && - Scalar::template Convert(elt).flags.test( - RealFlag::Overflow)); - } - }, - realMold->u, xReal->u); - } - } else if (Expr * - intMold{UnwrapExpr>(args[1])}) { - if (const auto *xInt{UnwrapExpr>(folded)}) { - result.emplace(); - std::visit( - [&](const auto &mold, const auto &x) { - using IntType = typename std::decay_t::Result; - static_assert(IntType::category == TypeCategory::Integer); - using Scalar = typename IntType::Scalar; - using xType = typename std::decay_t::Result; - const auto &xConst{DEREF(UnwrapExpr>(x))}; - for (const auto &elt : xConst.values()) { - result->emplace_back( - Scalar::template ConvertSigned(elt).overflow); - } - }, - intMold->u, xInt->u); - } else if (Expr * - cRound{args.size() >= 3 - ? UnwrapExpr>(args[2]) - : nullptr}; - !cRound || IsActuallyConstant(*args[2]->UnwrapExpr())) { - if (const auto *xReal{UnwrapExpr>(folded)}) { - common::RoundingMode roundingMode{common::RoundingMode::ToZero}; - if (cRound && - common::visit( - [](const auto &x) { - using xType = - typename std::decay_t::Result; - return GetScalarConstantValue(x) - .value() - .IsTrue(); - }, - cRound->u)) { - // ROUND=.TRUE. - convert with NINT() - roundingMode = common::RoundingMode::TiesAwayFromZero; - } - result.emplace(); - std::visit( - [&](const auto &mold, const auto &x) { - using IntType = - typename std::decay_t::Result; - static_assert(IntType::category == TypeCategory::Integer); - using Scalar = typename IntType::Scalar; - using xType = typename std::decay_t::Result; - const auto &xConst{DEREF(UnwrapExpr>(x))}; - for (const auto &elt : xConst.values()) { - // Note that OUT_OF_RANGE(Inf/NaN) is .TRUE. for the - // real->integer case, but not for real->real. - result->emplace_back(!elt.IsFinite() || - elt.template ToInteger(roundingMode) - .flags.test(RealFlag::Overflow)); - } - }, - intMold->u, xReal->u); - } - } - } - if (result) { - if (auto extents{GetConstantExtents(context, folded)}) { - return Expr{ - Constant{std::move(*result), std::move(*extents)}}; - } - } - } - } + return RewriteOutOfRange(context, std::move(funcRef)); } else if (name == "parity") { return FoldAllAnyParity( context, std::move(funcRef), &Scalar::NEQV, Scalar{false}); diff --git a/flang/lib/Evaluate/int-power.h b/flang/lib/Evaluate/int-power.h index 0d6a133ae73c51c1374baa1ae36c33f262dbc906..2ee012ceb77a3804c2bcde272ff5182dd351af14 100644 --- a/flang/lib/Evaluate/int-power.h +++ b/flang/lib/Evaluate/int-power.h @@ -33,6 +33,10 @@ ValueWithRealFlags TimesIntPowerOf(const REAL &factor, const REAL &base, REAL squares{base}; int nbits{INT::bits - absPower.LEADZ()}; for (int j{0}; j < nbits; ++j) { + if (j > 0) { // avoid spurious overflow on last iteration + squares = + squares.Multiply(squares, rounding).AccumulateFlags(result.flags); + } if (absPower.BTEST(j)) { if (negativePower) { result.value = result.value.Divide(squares, rounding) @@ -42,8 +46,6 @@ ValueWithRealFlags TimesIntPowerOf(const REAL &factor, const REAL &base, .AccumulateFlags(result.flags); } } - squares = - squares.Multiply(squares, rounding).AccumulateFlags(result.flags); } } return result; diff --git a/flang/lib/Evaluate/integer.cpp b/flang/lib/Evaluate/integer.cpp index e8173b44e873f14dc6a47d62417253412eee51d5..b982a3a0796cc5ce394c20d213c12997a1ec38af 100644 --- a/flang/lib/Evaluate/integer.cpp +++ b/flang/lib/Evaluate/integer.cpp @@ -14,7 +14,7 @@ template class Integer<8>; template class Integer<16>; template class Integer<32>; template class Integer<64>; -template class Integer<80>; +template class Integer<80, true, 16, std::uint16_t, std::uint32_t, 128>; template class Integer<128>; // Sanity checks against misconfiguration bugs diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 7226d69f6391c71f23d1009269a94d2efb1ec581..f07f94b1a022c9f02db49c4b6be527690714694d 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -2862,7 +2862,8 @@ std::optional IntrinsicProcTable::Implementation::HandleC_Loc( characteristics::DummyArgument{"x"s, characteristics::DummyDataObject{ std::move(*typeAndShape)}}}, - characteristics::Procedure::Attrs{}}}, + characteristics::Procedure::Attrs{ + characteristics::Procedure::Attr::Pure}}}, std::move(arguments)}; } } diff --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp index de4b21b7ca5f25f0dd7dc64216b34dbc0f89d6e2..223f67fee41dfc7b7b1bac4e25a16f6bb160ba64 100644 --- a/flang/lib/Evaluate/real.cpp +++ b/flang/lib/Evaluate/real.cpp @@ -788,6 +788,6 @@ template class Real, 11>; template class Real, 8>; template class Real, 24>; template class Real, 53>; -template class Real, 64>; +template class Real; template class Real, 113>; } // namespace Fortran::evaluate::value diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index f514a25b010241bc8db96ce66f62951b18c74a8c..9a5f9130632ee8158ef93e9c7f73ccebe426c9ec 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1056,8 +1056,8 @@ public: explicit FindImpureCallHelper(FoldingContext &c) : Base{*this}, context_{c} {} using Base::operator(); Result operator()(const ProcedureRef &call) const { - if (auto chars{ - characteristics::Procedure::Characterize(call.proc(), context_)}) { + if (auto chars{characteristics::Procedure::Characterize( + call.proc(), context_, /*emitError=*/false)}) { if (chars->attrs.test(characteristics::Procedure::Attr::Pure)) { return (*this)(call.arguments()); } diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index e432c5a302754c3aea542b315d14854ff489b3e7..f1b7b53975398e31cf529fd53f169afa097a63fd 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -145,6 +145,7 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts, } opts.setDebugInfo(val.value()); if (val != llvm::codegenoptions::DebugLineTablesOnly && + val != llvm::codegenoptions::FullDebugInfo && val != llvm::codegenoptions::NoDebugInfo) { const auto debugWarning = diags.getCustomDiagID( clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0"); diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 8f251997ed401b819e2741422577e73e3272f68b..d91846dde95a839bdc0501ad3498f358905bd52a 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -809,7 +809,7 @@ void CodeGenAction::generateLLVMIR() { } // Create the pass pipeline - fir::createMLIRToLLVMPassPipeline(pm, config); + fir::createMLIRToLLVMPassPipeline(pm, config, getCurrentFile()); (void)mlir::applyPassManagerCLOptions(pm); // run the pass manager diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 47bd6ace4e4b56eae3f2aa263a9b0bf4d186e47f..8b62fe8c022f802272733773f16b3684d93378ca 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -3700,7 +3700,8 @@ private: using DummyAttr = Fortran::evaluate::characteristics::DummyDataObject::Attr; if (auto procedure = Fortran::evaluate::characteristics::Procedure::Characterize( - userDefinedAssignment.proc(), getFoldingContext())) + userDefinedAssignment.proc(), getFoldingContext(), + /*emitError=*/false)) if (!procedure->dummyArguments.empty()) if (const auto *dataArg = std::get_if< Fortran::evaluate::characteristics::DummyDataObject>( diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 2d4d17a2ef12e9e799f775d773d3170a50aba64a..5ad244600328ca47b7fec9427ecbf5f9e205c0d5 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -218,7 +218,7 @@ Fortran::lower::CallerInterface::characterize() const { converter.getFoldingContext(); std::optional characteristic = Fortran::evaluate::characteristics::Procedure::Characterize( - procRef.proc(), foldingContext); + procRef.proc(), foldingContext, /*emitError=*/false); assert(characteristic && "Failed to get characteristic from procRef"); // The characteristic may not contain the argument characteristic if the // ProcedureDesignator has no interface, or may mismatch in case of implicit @@ -1571,7 +1571,7 @@ public: Fortran::lower::AbstractConverter &c) : CallInterface{c}, procDesignator{&procDes}, proc{Fortran::evaluate::characteristics::Procedure::Characterize( - procDes, converter.getFoldingContext()) + procDes, converter.getFoldingContext(), /*emitError=*/false) .value()} {} /// Does the procedure characteristics being translated have alternate /// returns ? @@ -1696,7 +1696,7 @@ bool Fortran::lower::mustPassLengthWithDummyProcedure( Fortran::lower::AbstractConverter &converter) { std::optional characteristics = Fortran::evaluate::characteristics::Procedure::Characterize( - procedure, converter.getFoldingContext()); + procedure, converter.getFoldingContext(), /*emitError=*/false); return ::mustPassLengthWithDummyProcedure(characteristics); } diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 5a42e6a6aa4175b45d76e261af9fc8b703636406..8bb2f83282b5565fd651f439f42f55b84443cd34 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -136,7 +136,7 @@ void DataSharingProcessor::insertBarrier() { void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { bool cmpCreated = false; - mlir::OpBuilder::InsertPoint localInsPt = firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); for (const omp::Clause &clause : clauses) { if (clause.id != llvm::omp::OMPC_lastprivate) continue; @@ -203,12 +203,11 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { // Lastprivate operation is inserted at the end // of the lexically last section in the sections // construct - mlir::OpBuilder::InsertPoint unstructuredSectionsIP = - firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard unstructuredSectionsGuard( + firOpBuilder); mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); firOpBuilder.setInsertionPoint(lastOper); lastPrivIP = firOpBuilder.saveInsertionPoint(); - firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP); } } } else if (mlir::isa(op)) { @@ -268,7 +267,6 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { "simd/worksharing-loop"); } } - firOpBuilder.restoreInsertionPoint(localInsPt); } void DataSharingProcessor::collectSymbols( @@ -372,7 +370,7 @@ void DataSharingProcessor::doPrivatize( uniquePrivatizerName)) return existingPrivatizer; - auto ip = firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); firOpBuilder.setInsertionPoint(&moduleOp.getBodyRegion().front(), moduleOp.getBodyRegion().front().begin()); auto result = firOpBuilder.create( @@ -424,7 +422,6 @@ void DataSharingProcessor::doPrivatize( } symTable->popScope(); - firOpBuilder.restoreInsertionPoint(ip); return result; }(); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 4424788e0132e28424cff3bf5cd8d8ca6ff19dc4..e932f7c284bca89fc60cc6ab0115ef687a8e5807 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -134,7 +134,7 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); - mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); // If the symbol corresponds to the original ThreadprivateOp, use the symbol @@ -197,8 +197,6 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, getExtendedValue(sexv, symThreadprivateValue); converter.bindSymbol(*sym, symThreadprivateExv); } - - firOpBuilder.restoreInsertionPoint(insPt); } static mlir::Operation * @@ -1091,16 +1089,12 @@ static void genParallelClauses( static void genSectionsClauses(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, - bool clausesFromBeginSections, mlir::omp::SectionsClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); - if (clausesFromBeginSections) { - cp.processAllocate(clauseOps); - cp.processSectionsReduction(loc, clauseOps); - // TODO Support delayed privatization. - } else { - cp.processNowait(clauseOps); - } + cp.processAllocate(clauseOps); + cp.processSectionsReduction(loc, clauseOps); + cp.processNowait(clauseOps); + // TODO Support delayed privatization. } static void genSimdClauses(Fortran::lower::AbstractConverter &converter, @@ -1121,16 +1115,13 @@ static void genSimdClauses(Fortran::lower::AbstractConverter &converter, static void genSingleClauses(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, - const List &beginClauses, - const List &endClauses, mlir::Location loc, + const List &clauses, mlir::Location loc, mlir::omp::SingleClauseOps &clauseOps) { - ClauseProcessor bcp(converter, semaCtx, beginClauses); - bcp.processAllocate(clauseOps); + ClauseProcessor cp(converter, semaCtx, clauses); + cp.processAllocate(clauseOps); + cp.processCopyprivate(loc, clauseOps); + cp.processNowait(clauseOps); // TODO Support delayed privatization. - - ClauseProcessor ecp(converter, semaCtx, endClauses); - ecp.processCopyprivate(loc, clauseOps); - ecp.processNowait(clauseOps); } static void genTargetClauses( @@ -1280,30 +1271,25 @@ static void genWsloopClauses( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::StatementContext &stmtCtx, - Fortran::lower::pft::Evaluation &eval, const List &beginClauses, - const List &endClauses, mlir::Location loc, - mlir::omp::WsloopClauseOps &clauseOps, + Fortran::lower::pft::Evaluation &eval, const List &clauses, + mlir::Location loc, mlir::omp::WsloopClauseOps &clauseOps, llvm::SmallVectorImpl &iv, llvm::SmallVectorImpl &reductionTypes, llvm::SmallVectorImpl &reductionSyms) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - ClauseProcessor bcp(converter, semaCtx, beginClauses); - bcp.processCollapse(loc, eval, clauseOps, iv); - bcp.processOrdered(clauseOps); - bcp.processReduction(loc, clauseOps, &reductionTypes, &reductionSyms); - bcp.processSchedule(stmtCtx, clauseOps); + ClauseProcessor cp(converter, semaCtx, clauses); + cp.processCollapse(loc, eval, clauseOps, iv); + cp.processNowait(clauseOps); + cp.processOrdered(clauseOps); + cp.processReduction(loc, clauseOps, &reductionTypes, &reductionSyms); + cp.processSchedule(stmtCtx, clauseOps); clauseOps.loopInclusiveAttr = firOpBuilder.getUnitAttr(); // TODO Support delayed privatization. if (ReductionProcessor::doReductionByRef(clauseOps.reductionVars)) clauseOps.reductionByRefAttr = firOpBuilder.getUnitAttr(); - if (!endClauses.empty()) { - ClauseProcessor ecp(converter, semaCtx, endClauses); - ecp.processNowait(clauseOps); - } - - bcp.processTODO( + cp.processTODO( loc, llvm::omp::Directive::OMPD_do); } @@ -1557,17 +1543,15 @@ static mlir::omp::SingleOp genSingleOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &beginClauses, - const List &endClauses) { + mlir::Location loc, const List &clauses) { mlir::omp::SingleClauseOps clauseOps; - genSingleClauses(converter, semaCtx, beginClauses, endClauses, loc, - clauseOps); + genSingleClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, loc, eval, llvm::omp::Directive::OMPD_single) .setGenNested(genNested) - .setClauses(&beginClauses), + .setClauses(&clauses), clauseOps); } @@ -1816,8 +1800,8 @@ static mlir::omp::WsloopOp genWsloopOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &beginClauses, const List &endClauses) { - DataSharingProcessor dsp(converter, semaCtx, beginClauses, eval); + const List &clauses) { + DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; @@ -1825,10 +1809,10 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector iv; llvm::SmallVector reductionTypes; llvm::SmallVector reductionSyms; - genWsloopClauses(converter, semaCtx, stmtCtx, eval, beginClauses, endClauses, - loc, clauseOps, iv, reductionTypes, reductionSyms); + genWsloopClauses(converter, semaCtx, stmtCtx, eval, clauses, loc, clauseOps, + iv, reductionTypes, reductionSyms); - auto *nestedEval = getCollapsedLoopEval(eval, getCollapseValue(beginClauses)); + auto *nestedEval = getCollapsedLoopEval(eval, getCollapseValue(clauses)); auto ivCallback = [&](mlir::Operation *op) { return genLoopAndReductionVars(op, converter, loc, iv, reductionSyms, @@ -1838,7 +1822,7 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval, llvm::omp::Directive::OMPD_do) - .setClauses(&beginClauses) + .setClauses(&clauses) .setDataSharingProcessor(&dsp) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(ivCallback), @@ -1849,19 +1833,20 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, // Code generation functions for composite constructs //===----------------------------------------------------------------------===// -static void genCompositeDistributeParallelDo( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &beginClauses, - const List &endClauses, mlir::Location loc) { +static void +genCompositeDistributeParallelDo(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const List &clauses, + mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } static void genCompositeDistributeParallelDoSimd( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &beginClauses, - const List &endClauses, mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, const List &clauses, + mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } @@ -1869,18 +1854,16 @@ static void genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &beginClauses, - const List &endClauses, mlir::Location loc) { + const List &clauses, mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE SIMD"); } static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &beginClauses, - const List &endClauses, + const List &clauses, mlir::Location loc) { - ClauseProcessor cp(converter, semaCtx, beginClauses); + ClauseProcessor cp(converter, semaCtx, clauses); cp.processTODO( loc, llvm::omp::OMPD_do_simd); @@ -1892,15 +1875,14 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - genWsloopOp(converter, semaCtx, eval, loc, beginClauses, endClauses); + genWsloopOp(converter, semaCtx, eval, loc, clauses); } static void genCompositeTaskloopSimd(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &beginClauses, - const List &endClauses, mlir::Location loc) { + const List &clauses, mlir::Location loc) { TODO(loc, "Composite TASKLOOP SIMD"); } @@ -2172,49 +2154,44 @@ genOMP(Fortran::lower::AbstractConverter &converter, converter.genLocation(beginBlockDirective.source); const auto origDirective = std::get(beginBlockDirective.t).v; - List beginClauses = makeClauses( + List clauses = makeClauses( std::get(beginBlockDirective.t), semaCtx); - List endClauses = makeClauses( - std::get(endBlockDirective.t), semaCtx); + clauses.append(makeClauses( + std::get(endBlockDirective.t), semaCtx)); assert(llvm::omp::blockConstructSet.test(origDirective) && "Expected block construct"); - for (const Clause &clause : beginClauses) { + for (const Clause &clause : clauses) { mlir::Location clauseLocation = converter.genLocation(clause.source); - if (!std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u)) { + if (!std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u)) { TODO(clauseLocation, "OpenMP Block construct clause"); } } - for (const Clause &clause : endClauses) { - mlir::Location clauseLocation = converter.genLocation(clause.source); - if (!std::get_if(&clause.u) && - !std::get_if(&clause.u)) - TODO(clauseLocation, "OpenMP Block construct clause"); - } - std::optional nextDir = origDirective; bool outermostLeafConstruct = true; while (nextDir) { @@ -2230,44 +2207,42 @@ genOMP(Fortran::lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_ordered: // 2.17.9 ORDERED construct. genOrderedRegionOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_parallel: // 2.6 PARALLEL construct. genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, beginClauses, outerCombined); + currentLocation, clauses, outerCombined); break; case llvm::omp::Directive::OMPD_single: // 2.8.2 SINGLE construct. genSingleOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, endClauses); + clauses); break; case llvm::omp::Directive::OMPD_target: // 2.12.5 TARGET construct. - genTargetOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, outerCombined); + genTargetOp(converter, semaCtx, eval, genNested, currentLocation, clauses, + outerCombined); break; case llvm::omp::Directive::OMPD_target_data: // 2.12.2 TARGET DATA construct. genTargetDataOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_task: // 2.10.1 TASK construct. - genTaskOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + genTaskOp(converter, semaCtx, eval, genNested, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_taskgroup: // 2.17.6 TASKGROUP construct. genTaskgroupOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_teams: // 2.7 TEAMS construct. // FIXME Pass the outerCombined argument or rename it to better describe // what it represents if it must always be `false` in this context. - genTeamsOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + genTeamsOp(converter, semaCtx, eval, genNested, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_workshare: // 2.8.3 WORKSHARE construct. @@ -2275,7 +2250,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, // implementation for this feature will come later. For the codes // that use this construct, add a single construct for now. genSingleOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, endClauses); + clauses); break; default: llvm_unreachable("Unexpected block construct"); @@ -2317,7 +2292,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { const auto &beginLoopDirective = std::get(loopConstruct.t); - List beginClauses = makeClauses( + List clauses = makeClauses( std::get(beginLoopDirective.t), semaCtx); mlir::Location currentLocation = converter.genLocation(beginLoopDirective.source); @@ -2327,16 +2302,13 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, assert(llvm::omp::loopConstructSet.test(origDirective) && "Expected loop construct"); - List endClauses = [&]() { - if (auto &endLoopDirective = - std::get>( - loopConstruct.t)) { - return makeClauses( - std::get(endLoopDirective->t), - semaCtx); - } - return List{}; - }(); + if (auto &endLoopDirective = + std::get>( + loopConstruct.t)) { + clauses.append(makeClauses( + std::get(endLoopDirective->t), + semaCtx)); + } std::optional nextDir = origDirective; while (nextDir) { @@ -2347,29 +2319,27 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, switch (leafDir) { case llvm::omp::Directive::OMPD_distribute_parallel_do: // 2.9.4.3 DISTRIBUTE PARALLEL Worksharing-Loop construct. - genCompositeDistributeParallelDo(converter, semaCtx, eval, beginClauses, - endClauses, currentLocation); + genCompositeDistributeParallelDo(converter, semaCtx, eval, clauses, + currentLocation); break; case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: // 2.9.4.4 DISTRIBUTE PARALLEL Worksharing-Loop SIMD construct. - genCompositeDistributeParallelDoSimd(converter, semaCtx, eval, - beginClauses, endClauses, + genCompositeDistributeParallelDoSimd(converter, semaCtx, eval, clauses, currentLocation); break; case llvm::omp::Directive::OMPD_distribute_simd: // 2.9.4.2 DISTRIBUTE SIMD construct. - genCompositeDistributeSimd(converter, semaCtx, eval, beginClauses, - endClauses, currentLocation); + genCompositeDistributeSimd(converter, semaCtx, eval, clauses, + currentLocation); break; case llvm::omp::Directive::OMPD_do_simd: // 2.9.3.2 Worksharing-Loop SIMD construct. - genCompositeDoSimd(converter, semaCtx, eval, beginClauses, endClauses, - currentLocation); + genCompositeDoSimd(converter, semaCtx, eval, clauses, currentLocation); break; case llvm::omp::Directive::OMPD_taskloop_simd: // 2.10.3 TASKLOOP SIMD construct. - genCompositeTaskloopSimd(converter, semaCtx, eval, beginClauses, - endClauses, currentLocation); + genCompositeTaskloopSimd(converter, semaCtx, eval, clauses, + currentLocation); break; default: llvm_unreachable("Unexpected composite construct"); @@ -2380,12 +2350,11 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_distribute: // 2.9.4.1 DISTRIBUTE construct. genDistributeOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_do: // 2.9.2 Worksharing-Loop construct. - genWsloopOp(converter, semaCtx, eval, currentLocation, beginClauses, - endClauses); + genWsloopOp(converter, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_parallel: // 2.6 PARALLEL construct. @@ -2394,21 +2363,21 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, // Maybe rename the argument if it represents something else or // initialize it properly. genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, beginClauses, + currentLocation, clauses, /*outerCombined=*/true); break; case llvm::omp::Directive::OMPD_simd: // 2.9.3.1 SIMD construct. - genSimdOp(converter, semaCtx, eval, currentLocation, beginClauses); + genSimdOp(converter, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_target: // 2.12.5 TARGET construct. genTargetOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, /*outerCombined=*/true); + clauses, /*outerCombined=*/true); break; case llvm::omp::Directive::OMPD_taskloop: // 2.10.2 TASKLOOP construct. - genTaskloopOp(converter, semaCtx, eval, currentLocation, beginClauses); + genTaskloopOp(converter, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_teams: // 2.7 TEAMS construct. @@ -2417,7 +2386,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, // Maybe rename the argument if it represents something else or // initialize it properly. genTeamsOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, /*outerCombined=*/true); + clauses, /*outerCombined=*/true); break; case llvm::omp::Directive::OMPD_loop: case llvm::omp::Directive::OMPD_masked: @@ -2453,16 +2422,20 @@ genOMP(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OpenMPSectionsConstruct §ionsConstruct) { const auto &beginSectionsDirective = std::get(sectionsConstruct.t); - List beginClauses = makeClauses( + List clauses = makeClauses( std::get(beginSectionsDirective.t), semaCtx); + const auto &endSectionsDirective = + std::get(sectionsConstruct.t); + clauses.append(makeClauses( + std::get(endSectionsDirective.t), + semaCtx)); // Process clauses before optional omp.parallel, so that new variables are // allocated outside of the parallel region mlir::Location currentLocation = converter.getCurrentLocation(); mlir::omp::SectionsClauseOps clauseOps; - genSectionsClauses(converter, semaCtx, beginClauses, currentLocation, - /*clausesFromBeginSections=*/true, clauseOps); + genSectionsClauses(converter, semaCtx, clauses, currentLocation, clauseOps); // Parallel wrapper of PARALLEL SECTIONS construct llvm::omp::Directive dir = @@ -2470,16 +2443,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, .v; if (dir == llvm::omp::Directive::OMPD_parallel_sections) { genParallelOp(converter, symTable, semaCtx, eval, - /*genNested=*/false, currentLocation, beginClauses, + /*genNested=*/false, currentLocation, clauses, /*outerCombined=*/true); - } else { - const auto &endSectionsDirective = - std::get(sectionsConstruct.t); - List endClauses = makeClauses( - std::get(endSectionsDirective.t), - semaCtx); - genSectionsClauses(converter, semaCtx, endClauses, currentLocation, - /*clausesFromBeginSections=*/false, clauseOps); } // SECTIONS construct. @@ -2494,7 +2459,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) { symTable.pushScope(); genSectionOp(converter, semaCtx, neval, /*genNested=*/true, currentLocation, - beginClauses); + clauses); symTable.popScope(); firOpBuilder.restoreInsertionPoint(ip); } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index f42386fe2736ddc927b48a2f66a34255f62a06ed..23fabaf34abac1d43cbe6ab13ad65bb2f66503de 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -220,12 +220,12 @@ mlir::Value ReductionProcessor::createScalarCombiner( switch (redId) { case ReductionIdentifier::MAX: reductionOp = - getReductionOperation( + getReductionOperation( builder, type, loc, op1, op2); break; case ReductionIdentifier::MIN: reductionOp = - getReductionOperation( + getReductionOperation( builder, type, loc, op1, op2); break; case ReductionIdentifier::IOR: @@ -301,10 +301,11 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, ReductionProcessor::ReductionIdentifier redId, fir::BaseBoxType boxTy, mlir::Value lhs, mlir::Value rhs) { - fir::SequenceType seqTy = - mlir::dyn_cast_or_null(boxTy.getEleTy()); - // TODO: support allocatable arrays: !fir.box>> - if (!seqTy || seqTy.hasUnknownShape()) + fir::SequenceType seqTy = mlir::dyn_cast_or_null( + fir::unwrapRefType(boxTy.getEleTy())); + fir::HeapType heapTy = + mlir::dyn_cast_or_null(boxTy.getEleTy()); + if ((!seqTy || seqTy.hasUnknownShape()) && !heapTy) TODO(loc, "Unsupported boxed type in OpenMP reduction"); // load fir.ref> @@ -312,6 +313,23 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, lhs = builder.create(loc, lhs); rhs = builder.create(loc, rhs); + if (heapTy && !seqTy) { + // get box contents (heap pointers) + lhs = builder.create(loc, lhs); + rhs = builder.create(loc, rhs); + mlir::Value lhsValAddr = lhs; + + // load heap pointers + lhs = builder.create(loc, lhs); + rhs = builder.create(loc, rhs); + + mlir::Value result = ReductionProcessor::createScalarCombiner( + builder, loc, redId, heapTy.getEleTy(), lhs, rhs); + builder.create(loc, result, lhsValAddr); + builder.create(loc, lhsAddr); + return; + } + const unsigned rank = seqTy.getDimension(); llvm::SmallVector extents; extents.reserve(rank); @@ -338,6 +356,10 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, // Iterate over array elements, applying the equivalent scalar reduction: + // F2018 5.4.10.2: Unallocated allocatable variables may not be referenced + // and so no null check is needed here before indexing into the (possibly + // allocatable) arrays. + // A hlfir::elemental here gets inlined with a temporary so create the // loop nest directly. // This function already controls all of the code in this region so we @@ -412,9 +434,11 @@ createReductionCleanupRegion(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type valTy = fir::unwrapRefType(redTy); if (auto boxTy = mlir::dyn_cast_or_null(valTy)) { - mlir::Type innerTy = fir::extractSequenceType(boxTy); - if (!mlir::isa(innerTy)) - typeError(); + if (!mlir::isa(boxTy.getEleTy())) { + mlir::Type innerTy = fir::extractSequenceType(boxTy); + if (!mlir::isa(innerTy)) + typeError(); + } mlir::Value arg = block->getArgument(0); arg = builder.loadIfRef(loc, arg); @@ -443,6 +467,19 @@ createReductionCleanupRegion(fir::FirOpBuilder &builder, mlir::Location loc, typeError(); } +// like fir::unwrapSeqOrBoxedSeqType except it also works for non-sequence boxes +static mlir::Type unwrapSeqOrBoxedType(mlir::Type ty) { + if (auto seqTy = ty.dyn_cast()) + return seqTy.getEleTy(); + if (auto boxTy = ty.dyn_cast()) { + auto eleTy = fir::unwrapRefType(boxTy.getEleTy()); + if (auto seqTy = eleTy.dyn_cast()) + return seqTy.getEleTy(); + return eleTy; + } + return ty; +} + static mlir::Value createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, mlir::omp::DeclareReductionOp &reductionDecl, @@ -450,7 +487,7 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type, bool isByRef) { mlir::Type ty = fir::unwrapRefType(type); mlir::Value initValue = ReductionProcessor::getReductionInitValue( - loc, fir::unwrapSeqOrBoxedSeqType(ty), redId, builder); + loc, unwrapSeqOrBoxedType(ty), redId, builder); if (fir::isa_trivial(ty)) { if (isByRef) { @@ -462,15 +499,69 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, return initValue; } + // check if an allocatable box is unallocated. If so, initialize the boxAlloca + // to be unallocated e.g. + // %box_alloca = fir.alloca !fir.box> + // %addr = fir.box_addr %box + // if (%addr == 0) { + // %nullbox = fir.embox %addr + // fir.store %nullbox to %box_alloca + // } else { + // // ... + // fir.store %something to %box_alloca + // } + // omp.yield %box_alloca + mlir::Value blockArg = + builder.loadIfRef(loc, builder.getBlock()->getArgument(0)); + auto handleNullAllocatable = [&](mlir::Value boxAlloca) -> fir::IfOp { + mlir::Value addr = builder.create(loc, blockArg); + mlir::Value isNotAllocated = builder.genIsNullAddr(loc, addr); + fir::IfOp ifOp = builder.create(loc, isNotAllocated, + /*withElseRegion=*/true); + builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); + // just embox the null address and return + mlir::Value nullBox = builder.create(loc, ty, addr); + builder.create(loc, nullBox, boxAlloca); + return ifOp; + }; + // all arrays are boxed if (auto boxTy = mlir::dyn_cast_or_null(ty)) { - assert(isByRef && "passing arrays by value is unsupported"); - // TODO: support allocatable arrays: !fir.box>> - mlir::Type innerTy = fir::extractSequenceType(boxTy); + assert(isByRef && "passing boxes by value is unsupported"); + bool isAllocatable = mlir::isa(boxTy.getEleTy()); + mlir::Value boxAlloca = builder.create(loc, ty); + mlir::Type innerTy = fir::unwrapRefType(boxTy.getEleTy()); + if (fir::isa_trivial(innerTy)) { + // boxed non-sequence value e.g. !fir.box> + if (!isAllocatable) + TODO(loc, "Reduction of non-allocatable trivial typed box"); + + fir::IfOp ifUnallocated = handleNullAllocatable(boxAlloca); + + builder.setInsertionPointToStart(&ifUnallocated.getElseRegion().front()); + mlir::Value valAlloc = builder.create(loc, innerTy); + builder.createStoreWithConvert(loc, initValue, valAlloc); + mlir::Value box = builder.create(loc, ty, valAlloc); + builder.create(loc, box, boxAlloca); + + auto insPt = builder.saveInsertionPoint(); + createReductionCleanupRegion(builder, loc, reductionDecl); + builder.restoreInsertionPoint(insPt); + builder.setInsertionPointAfter(ifUnallocated); + return boxAlloca; + } + innerTy = fir::extractSequenceType(boxTy); if (!mlir::isa(innerTy)) TODO(loc, "Unsupported boxed type for reduction"); + + fir::IfOp ifUnallocated{nullptr}; + if (isAllocatable) { + ifUnallocated = handleNullAllocatable(boxAlloca); + builder.setInsertionPointToStart(&ifUnallocated.getElseRegion().front()); + } + // Create the private copy from the initial fir.box: - hlfir::Entity source = hlfir::Entity{builder.getBlock()->getArgument(0)}; + hlfir::Entity source = hlfir::Entity{blockArg}; // Allocating on the heap in case the whole reduction is nested inside of a // loop @@ -478,24 +569,29 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, // work by inserting stacksave/stackrestore around the reduction in // openmpirbuilder auto [temp, needsDealloc] = createTempFromMold(loc, builder, source); - // if needsDealloc isn't statically false, add cleanup region. TODO: always + // if needsDealloc isn't statically false, add cleanup region. Always // do this for allocatable boxes because they might have been re-allocated // in the body of the loop/parallel region + std::optional cstNeedsDealloc = fir::getIntIfConstant(needsDealloc); assert(cstNeedsDealloc.has_value() && "createTempFromMold decides this statically"); if (cstNeedsDealloc.has_value() && *cstNeedsDealloc != false) { - auto insPt = builder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(builder); createReductionCleanupRegion(builder, loc, reductionDecl); - builder.restoreInsertionPoint(insPt); + } else { + assert(!isAllocatable && "Allocatable arrays must be heap allocated"); } // Put the temporary inside of a box: hlfir::Entity box = hlfir::genVariableBox(loc, builder, temp); - builder.create(loc, initValue, box); - mlir::Value boxAlloca = builder.create(loc, ty); - builder.create(loc, box, boxAlloca); + // hlfir::genVariableBox removes fir.heap<> around the element type + mlir::Value convertedBox = builder.createConvert(loc, ty, box.getBase()); + builder.create(loc, initValue, convertedBox); + builder.create(loc, convertedBox, boxAlloca); + if (ifUnallocated) + builder.setInsertionPointAfter(ifUnallocated); return boxAlloca; } diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index e144640081cbf33649243e7a3cbac3b3d9fc614e..c403b9effbfac6432553e8320c22df8e63937f24 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -29,7 +29,7 @@ using namespace mlir; //===----------------------------------------------------------------------===// static bool isDummyArgument(mlir::Value v) { - auto blockArg{v.dyn_cast()}; + auto blockArg{mlir::dyn_cast(v)}; if (!blockArg) return false; diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index b09da4929a8a27d6d351d54663d4f2508436ba63..a0fbae5b614cc720ba3052da847ef30ccec24cf5 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -250,7 +250,7 @@ mlir::Block *fir::FirOpBuilder::getAllocaBlock() { .getParentOfType()) { return ompOutlineableIface.getAllocaBlock(); } - if (mlir::isa(getRegion().getParentOp())) + if (getRegion().getParentOfType()) return &getRegion().front(); if (auto accRecipeIface = getRegion().getParentOfType()) { diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index d909bda89cdeb40c1b342ecfdd73305750ac550c..921eac2f8f4b60bda5ed6e8ab8762d449526e000 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2110,9 +2110,8 @@ struct XArrayCoorOpConversion const bool baseIsBoxed = coor.getMemref().getType().isa(); TypePair baseBoxTyPair = baseIsBoxed ? getBoxTypePair(coor.getMemref().getType()) : TypePair{}; - mlir::LLVM::IntegerOverflowFlagsAttr nsw = - mlir::LLVM::IntegerOverflowFlagsAttr::get( - rewriter.getContext(), mlir::LLVM::IntegerOverflowFlags::nsw); + mlir::LLVM::IntegerOverflowFlags nsw = + mlir::LLVM::IntegerOverflowFlags::nsw; // For each dimension of the array, generate the offset calculation. for (unsigned i = 0; i < rank; ++i, ++indexOffset, ++shapeOffset, @@ -2396,9 +2395,8 @@ private: auto cpnTy = fir::dyn_cast_ptrOrBoxEleTy(boxObjTy); mlir::Type llvmPtrTy = ::getLlvmPtrType(coor.getContext()); mlir::Type byteTy = ::getI8Type(coor.getContext()); - mlir::LLVM::IntegerOverflowFlagsAttr nsw = - mlir::LLVM::IntegerOverflowFlagsAttr::get( - rewriter.getContext(), mlir::LLVM::IntegerOverflowFlags::nsw); + mlir::LLVM::IntegerOverflowFlags nsw = + mlir::LLVM::IntegerOverflowFlags::nsw; for (unsigned i = 1, last = operands.size(); i < last; ++i) { if (auto arrTy = cpnTy.dyn_cast()) { diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 5c24c95db427aa9e2a325a0112547da53f42f0a6..24af94f9b90a1dfd5bf59e0261264e6856c5b3eb 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -2165,7 +2165,7 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser, } fir::DoLoopOp fir::getForInductionVarOwner(mlir::Value val) { - auto ivArg = val.dyn_cast(); + auto ivArg = mlir::dyn_cast(val); if (!ivArg) return {}; assert(ivArg.getOwner() && "unlinked block argument"); @@ -3777,7 +3777,7 @@ valueCheckFirAttributes(mlir::Value value, if (auto loadOp = mlir::dyn_cast(definingOp)) value = loadOp.getMemref(); // If this is a function argument, look in the argument attributes. - if (auto blockArg = value.dyn_cast()) { + if (auto blockArg = mlir::dyn_cast(value)) { if (blockArg.getOwner() && blockArg.getOwner()->isEntryBlock()) if (auto funcOp = mlir::dyn_cast( blockArg.getOwner()->getParentOp())) @@ -3907,7 +3907,7 @@ mlir::ParseResult parseCUFKernelValues( if (mlir::succeeded(parser.parseOptionalStar())) return mlir::success(); - if (parser.parseOptionalLParen()) { + if (mlir::succeeded(parser.parseOptionalLParen())) { if (mlir::failed(parser.parseCommaSeparatedList( mlir::AsmParser::Delimiter::None, [&]() { if (parser.parseOperand(values.emplace_back())) @@ -3915,11 +3915,17 @@ mlir::ParseResult parseCUFKernelValues( return mlir::success(); }))) return mlir::failure(); + auto builder = parser.getBuilder(); + for (size_t i = 0; i < values.size(); i++) { + types.emplace_back(builder.getI32Type()); + } if (parser.parseRParen()) return mlir::failure(); } else { if (parser.parseOperand(values.emplace_back())) return mlir::failure(); + auto builder = parser.getBuilder(); + types.emplace_back(builder.getI32Type()); return mlir::success(); } return mlir::success(); diff --git a/flang/lib/Optimizer/Transforms/AbstractResult.cpp b/flang/lib/Optimizer/Transforms/AbstractResult.cpp index dd1ddd16f2ded5a5c8a6473339d306a0ccf8133b..eb4dd637bb167e88b44320cb211139d1e609c320 100644 --- a/flang/lib/Optimizer/Transforms/AbstractResult.cpp +++ b/flang/lib/Optimizer/Transforms/AbstractResult.cpp @@ -16,13 +16,12 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Diagnostics.h" #include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" #include "mlir/Transforms/DialectConversion.h" -#include "mlir/Transforms/Passes.h" #include "llvm/ADT/TypeSwitch.h" namespace fir { -#define GEN_PASS_DEF_ABSTRACTRESULTONFUNCOPT -#define GEN_PASS_DEF_ABSTRACTRESULTONGLOBALOPT +#define GEN_PASS_DEF_ABSTRACTRESULTOPT #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir @@ -285,59 +284,12 @@ private: bool shouldBoxResult; }; -/// @brief Base CRTP class for AbstractResult pass family. -/// Contains common logic for abstract result conversion in a reusable fashion. -/// @tparam Pass target class that implements operation-specific logic. -/// @tparam PassBase base class template for the pass generated by TableGen. -/// The `Pass` class must define runOnSpecificOperation(OpTy, bool, -/// mlir::RewritePatternSet&, mlir::ConversionTarget&) member function. -/// This function should implement operation-specific functionality. -template class PassBase> -class AbstractResultOptTemplate : public PassBase { +class AbstractResultOpt + : public fir::impl::AbstractResultOptBase { public: - void runOnOperation() override { - auto *context = &this->getContext(); - auto op = this->getOperation(); - - mlir::RewritePatternSet patterns(context); - mlir::ConversionTarget target = *context; - const bool shouldBoxResult = this->passResultAsBox.getValue(); - - auto &self = static_cast(*this); - self.runOnSpecificOperation(op, shouldBoxResult, patterns, target); - - // Convert the calls and, if needed, the ReturnOp in the function body. - target.addLegalDialect(); - target.addIllegalOp(); - target.addDynamicallyLegalOp([](fir::CallOp call) { - return !hasAbstractResult(call.getFunctionType()); - }); - target.addDynamicallyLegalOp([](fir::AddrOfOp addrOf) { - if (auto funTy = addrOf.getType().dyn_cast()) - return !hasAbstractResult(funTy); - return true; - }); - target.addDynamicallyLegalOp([](fir::DispatchOp dispatch) { - return !hasAbstractResult(dispatch.getFunctionType()); - }); - - patterns.insert>(context, shouldBoxResult); - patterns.insert>(context, shouldBoxResult); - patterns.insert(context); - patterns.insert(context, shouldBoxResult); - if (mlir::failed( - mlir::applyPartialConversion(op, target, std::move(patterns)))) { - mlir::emitError(op.getLoc(), "error in converting abstract results\n"); - this->signalPassFailure(); - } - } -}; + using fir::impl::AbstractResultOptBase< + AbstractResultOpt>::AbstractResultOptBase; -class AbstractResultOnFuncOpt - : public AbstractResultOptTemplate { -public: void runOnSpecificOperation(mlir::func::FuncOp func, bool shouldBoxResult, mlir::RewritePatternSet &patterns, mlir::ConversionTarget &target) { @@ -386,25 +338,20 @@ public: } } } -}; -inline static bool containsFunctionTypeWithAbstractResult(mlir::Type type) { - return mlir::TypeSwitch(type) - .Case([](fir::BoxProcType boxProc) { - return fir::hasAbstractResult( - boxProc.getEleTy().cast()); - }) - .Case([](fir::PointerType pointer) { - return fir::hasAbstractResult( - pointer.getEleTy().cast()); - }) - .Default([](auto &&) { return false; }); -} + inline static bool containsFunctionTypeWithAbstractResult(mlir::Type type) { + return mlir::TypeSwitch(type) + .Case([](fir::BoxProcType boxProc) { + return fir::hasAbstractResult( + boxProc.getEleTy().cast()); + }) + .Case([](fir::PointerType pointer) { + return fir::hasAbstractResult( + pointer.getEleTy().cast()); + }) + .Default([](auto &&) { return false; }); + } -class AbstractResultOnGlobalOpt - : public AbstractResultOptTemplate< - AbstractResultOnGlobalOpt, fir::impl::AbstractResultOnGlobalOptBase> { -public: void runOnSpecificOperation(fir::GlobalOp global, bool, mlir::RewritePatternSet &, mlir::ConversionTarget &) { @@ -412,14 +359,77 @@ public: TODO(global->getLoc(), "support for procedure pointers"); } } -}; -} // end anonymous namespace -} // namespace fir -std::unique_ptr fir::createAbstractResultOnFuncOptPass() { - return std::make_unique(); -} + /// Run the pass on a ModuleOp. This makes fir-opt --abstract-result work. + void runOnModule() { + mlir::ModuleOp mod = mlir::cast(getOperation()); + + auto pass = std::make_unique(); + pass->copyOptionValuesFrom(this); + mlir::OpPassManager pipeline; + pipeline.addPass(std::unique_ptr{pass.release()}); + + // Run the pass on all operations directly nested inside of the ModuleOp + // we can't just call runOnSpecificOperation here because the pass + // implementation only works when scoped to a particular func.func or + // fir.global + for (mlir::Region ®ion : mod->getRegions()) { + for (mlir::Block &block : region.getBlocks()) { + for (mlir::Operation &op : block.getOperations()) { + if (mlir::failed(runPipeline(pipeline, &op))) { + mlir::emitError(op.getLoc(), "Failed to run abstract result pass"); + signalPassFailure(); + return; + } + } + } + } + } -std::unique_ptr fir::createAbstractResultOnGlobalOptPass() { - return std::make_unique(); -} + void runOnOperation() override { + auto *context = &this->getContext(); + mlir::Operation *op = this->getOperation(); + if (mlir::isa(op)) { + runOnModule(); + return; + } + + mlir::RewritePatternSet patterns(context); + mlir::ConversionTarget target = *context; + const bool shouldBoxResult = this->passResultAsBox.getValue(); + + mlir::TypeSwitch(op) + .Case([&](auto op) { + runOnSpecificOperation(op, shouldBoxResult, patterns, target); + }); + + // Convert the calls and, if needed, the ReturnOp in the function body. + target.addLegalDialect(); + target.addIllegalOp(); + target.addDynamicallyLegalOp([](fir::CallOp call) { + return !hasAbstractResult(call.getFunctionType()); + }); + target.addDynamicallyLegalOp([](fir::AddrOfOp addrOf) { + if (auto funTy = addrOf.getType().dyn_cast()) + return !hasAbstractResult(funTy); + return true; + }); + target.addDynamicallyLegalOp([](fir::DispatchOp dispatch) { + return !hasAbstractResult(dispatch.getFunctionType()); + }); + + patterns.insert>(context, shouldBoxResult); + patterns.insert>(context, shouldBoxResult); + patterns.insert(context); + patterns.insert(context, shouldBoxResult); + if (mlir::failed( + mlir::applyPartialConversion(op, target, std::move(patterns)))) { + mlir::emitError(op->getLoc(), "error in converting abstract results\n"); + this->signalPassFailure(); + } + } +}; + +} // end anonymous namespace +} // namespace fir \ No newline at end of file diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 4ca338066128768b0f5b5532997dd2fb7e871171..68584bef055b61e2e4e23503c0225b893488dcd7 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -11,12 +11,14 @@ /// This pass populates some debug information for the module and functions. //===----------------------------------------------------------------------===// +#include "flang/Common/Version.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Dialect/Support/FIRContext.h" +#include "flang/Optimizer/Support/InternalNames.h" #include "flang/Optimizer/Transforms/Passes.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" @@ -28,12 +30,12 @@ #include "mlir/Transforms/RegionUtils.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" namespace fir { #define GEN_PASS_DEF_ADDDEBUGINFO -#define GEN_PASS_DECL_ADDDEBUGINFO #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir @@ -43,6 +45,7 @@ namespace { class AddDebugInfoPass : public fir::impl::AddDebugInfoBase { public: + AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} void runOnOperation() override; }; @@ -52,21 +55,40 @@ void AddDebugInfoPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); mlir::OpBuilder builder(context); - std::string inputFilePath("-"); - if (auto fileLoc = module.getLoc().dyn_cast()) - inputFilePath = fileLoc.getFilename().getValue(); + llvm::StringRef fileName; + std::string filePath; + // We need 2 type of file paths here. + // 1. Name of the file as was presented to compiler. This can be absolute + // or relative to 2. + // 2. Current working directory + // + // We are also dealing with 2 different situations below. One is normal + // compilation where we will have a value in 'inputFilename' and we can + // obtain the current directory using 'current_path'. + // The 2nd case is when this pass is invoked directly from 'fir-opt' tool. + // In that case, 'inputFilename' may be empty. Location embedded in the + // module will be used to get file name and its directory. + if (inputFilename.empty()) { + if (auto fileLoc = module.getLoc().dyn_cast()) { + fileName = llvm::sys::path::filename(fileLoc.getFilename().getValue()); + filePath = llvm::sys::path::parent_path(fileLoc.getFilename().getValue()); + } else + fileName = "-"; + } else { + fileName = inputFilename; + llvm::SmallString<256> cwd; + if (!llvm::sys::fs::current_path(cwd)) + filePath = cwd.str(); + } - auto getFileAttr = [context](llvm::StringRef path) -> mlir::LLVM::DIFileAttr { - return mlir::LLVM::DIFileAttr::get(context, llvm::sys::path::filename(path), - llvm::sys::path::parent_path(path)); - }; - - mlir::LLVM::DIFileAttr fileAttr = getFileAttr(inputFilePath); - mlir::StringAttr producer = mlir::StringAttr::get(context, "Flang"); + mlir::LLVM::DIFileAttr fileAttr = + mlir::LLVM::DIFileAttr::get(context, fileName, filePath); + mlir::StringAttr producer = + mlir::StringAttr::get(context, Fortran::common::getFlangFullVersion()); mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get( mlir::DistinctAttr::create(mlir::UnitAttr::get(context)), llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer, - /*isOptimized=*/false, mlir::LLVM::DIEmissionKind::LineTablesOnly); + isOptimized, debugLevel); module.walk([&](mlir::func::FuncOp funcOp) { mlir::Location l = funcOp->getLoc(); @@ -75,43 +97,49 @@ void AddDebugInfoPass::runOnOperation() { if (l.dyn_cast()) return; - llvm::StringRef funcFilePath; - if (l.dyn_cast()) - funcFilePath = - l.dyn_cast().getFilename().getValue(); - else - funcFilePath = inputFilePath; + unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry()) + ? llvm::dwarf::getCallingConvention("DW_CC_program") + : llvm::dwarf::getCallingConvention("DW_CC_normal"); + + if (auto funcLoc = l.dyn_cast()) { + fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue()); + filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue()); + } mlir::StringAttr funcName = mlir::StringAttr::get(context, funcOp.getName()); mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get( context, llvm::dwarf::DW_TAG_base_type, "void", /*sizeInBits=*/0, /*encoding=*/1); + // FIXME: Provide proper type for subroutine mlir::LLVM::DISubroutineTypeAttr subTypeAttr = - mlir::LLVM::DISubroutineTypeAttr::get( - context, llvm::dwarf::getCallingConvention("DW_CC_normal"), - {bT, bT}); - mlir::LLVM::DIFileAttr funcFileAttr = getFileAttr(funcFilePath); + mlir::LLVM::DISubroutineTypeAttr::get(context, CC, {bT, bT}); + mlir::LLVM::DIFileAttr funcFileAttr = + mlir::LLVM::DIFileAttr::get(context, fileName, filePath); // Only definitions need a distinct identifier and a compilation unit. mlir::DistinctAttr id; mlir::LLVM::DICompileUnitAttr compilationUnit; - auto subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized; + mlir::LLVM::DISubprogramFlags subprogramFlags = + mlir::LLVM::DISubprogramFlags{}; + if (isOptimized) + subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized; if (!funcOp.isExternal()) { id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); compilationUnit = cuAttr; subprogramFlags = subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; } + // FIXME: Provide proper line and scopeline. auto spAttr = mlir::LLVM::DISubprogramAttr::get( context, id, compilationUnit, fileAttr, funcName, funcName, - funcFileAttr, - /*line=*/1, - /*scopeline=*/1, subprogramFlags, subTypeAttr); + funcFileAttr, /*line=*/1, /*scopeline=*/1, subprogramFlags, + subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); }); } -std::unique_ptr fir::createAddDebugInfoPass() { - return std::make_unique(); +std::unique_ptr +fir::createAddDebugInfoPass(fir::AddDebugInfoOptions options) { + return std::make_unique(options); } diff --git a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp index d1831cf1c200cc20a027e960d939aaff260fab95..64531cb1868efe940c30faa35d8d232affd0c503 100644 --- a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp +++ b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp @@ -63,7 +63,7 @@ struct AffineFunctionAnalysis { } // namespace static bool analyzeCoordinate(mlir::Value coordinate, mlir::Operation *op) { - if (auto blockArg = coordinate.dyn_cast()) { + if (auto blockArg = mlir::dyn_cast(coordinate)) { if (isa(blockArg.getOwner()->getParentOp())) return true; LLVM_DEBUG(llvm::dbgs() << "AffineLoopAnalysis: array coordinate is not a " @@ -224,7 +224,7 @@ private: if (auto op = value.getDefiningOp()) if (auto intConstant = op.getValue().dyn_cast()) return toAffineExpr(intConstant.getInt()); - if (auto blockArg = value.dyn_cast()) { + if (auto blockArg = mlir::dyn_cast(value)) { affineArgs.push_back(value); if (isa(blockArg.getOwner()->getParentOp()) || isa(blockArg.getOwner()->getParentOp())) diff --git a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp index 18ca5711bfea8965eadf1c6dfc36d49e5d1e4206..a08d58383d3a91a7a7e59b7e295d37a17d038c39 100644 --- a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp +++ b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp @@ -187,7 +187,7 @@ public: LLVM_DEBUG(llvm::dbgs() << "popset: " << *op << '\n'); auto popFn = [&](auto rop) { assert(val && "op must have a result value"); - auto resNum = val.cast().getResultNumber(); + auto resNum = mlir::cast(val).getResultNumber(); llvm::SmallVector results; rop.resultToSourceOps(results, resNum); for (auto u : results) @@ -296,7 +296,7 @@ public: visited.insert(val); // Process a block argument. - if (auto ba = val.dyn_cast()) { + if (auto ba = mlir::dyn_cast(val)) { collectArrayMentionFrom(ba); return; } diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt index d55655c53906e62c6d77a24b77781d423f0c242e..fc08d67540ceb0770bdf469b6203c792b437f7f6 100644 --- a/flang/lib/Optimizer/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt @@ -35,6 +35,7 @@ add_flang_library(FIRTransforms FIRDialect FIRDialectSupport FIRSupport + FortranCommon HLFIRDialect MLIRAffineUtils MLIRFuncDialect diff --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp index a7244e1c58330a5b59f93ea98a2c7227a8ae84eb..b4c5660670579d51b184df1eec5adbf116234acd 100644 --- a/flang/lib/Semantics/check-allocate.cpp +++ b/flang/lib/Semantics/check-allocate.cpp @@ -611,6 +611,20 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) { return false; } } + if (allocateInfo_.gotPinned) { + std::optional cudaAttr{GetCUDADataAttr(ultimate_)}; + if (!cudaAttr || *cudaAttr != common::CUDADataAttr::Pinned) { + context.Say(name_.source, + "Object in ALLOCATE must have PINNED attribute when PINNED option is specified"_err_en_US); + } + } + if (allocateInfo_.gotStream) { + std::optional cudaAttr{GetCUDADataAttr(ultimate_)}; + if (!cudaAttr || *cudaAttr != common::CUDADataAttr::Device) { + context.Say(name_.source, + "Object in ALLOCATE must have DEVICE attribute when STREAM option is specified"_err_en_US); + } + } return RunCoarrayRelatedChecks(context); } diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index bd2f755855172a89a77cc31962b9934df1b970f3..ce82cccf26d54684f16e28df5aff561015806d70 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -1477,10 +1477,15 @@ static void CheckMaxMin(const characteristics::Procedure &proc, if (arguments[j]) { if (const auto *expr{arguments[j]->UnwrapExpr()}; expr && evaluate::MayBePassedAsAbsentOptional(*expr)) { - if (auto thisType{expr->GetType()}; - thisType && *thisType != typeAndShape->type()) { - messages.Say(arguments[j]->sourceLocation(), - "An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE"_err_en_US); + if (auto thisType{expr->GetType()}) { + if (thisType->category() == TypeCategory::Character && + typeAndShape->type().category() == TypeCategory::Character && + thisType->kind() == typeAndShape->type().kind()) { + // don't care about lengths + } else if (*thisType != typeAndShape->type()) { + messages.Say(arguments[j]->sourceLocation(), + "An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE"_err_en_US); + } } } } @@ -1597,8 +1602,8 @@ static void CheckReduce( if (const auto *expr{operation->UnwrapExpr()}) { if (const auto *designator{ std::get_if(&expr->u)}) { - procChars = - characteristics::Procedure::Characterize(*designator, context); + procChars = characteristics::Procedure::Characterize( + *designator, context, /*emitError=*/true); } else if (const auto *ref{ std::get_if(&expr->u)}) { procChars = characteristics::Procedure::Characterize(*ref, context); diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp index fb1ebadd3785864acb8c4b3d77023d49f8763220..a9e57de7e2f2b5834255d93b53bb1a671a29c6f9 100644 --- a/flang/lib/Semantics/check-cuda.cpp +++ b/flang/lib/Semantics/check-cuda.cpp @@ -344,6 +344,9 @@ private: [&](const common::Indirection &x) { WarnOnIoStmt(source); }, + [&](const common::Indirection &x) { + Check(x.value()); + }, [&](const auto &x) { if (auto msg{ActionStmtChecker::WhyNotOk(x)}) { context_.Say(source, std::move(*msg)); @@ -369,6 +372,13 @@ private: Check(std::get(eb->t)); } } + void Check(const parser::IfStmt &is) { + const auto &uS{ + std::get>(is.t)}; + CheckUnwrappedExpr( + context_, uS.source, std::get(is.t)); + Check(uS.statement, uS.source); + } void Check(const parser::LoopControl::Bounds &bounds) { Check(bounds.lower); Check(bounds.upper); diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 875929e90fdd3186c5ad20e9c886a7276b690782..901ac20f8aae9b2f77c1a814d15edfb9207144e1 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -948,17 +948,12 @@ void CheckHelper::CheckObjectEntity( "Component '%s' with ATTRIBUTES(DEVICE) must also be allocatable"_err_en_US, symbol.name()); } - if (IsAssumedSizeArray(symbol)) { - messages_.Say( - "Object '%s' with ATTRIBUTES(DEVICE) may not be assumed size"_err_en_US, - symbol.name()); - } break; case common::CUDADataAttr::Managed: if (!IsAutomatic(symbol) && !IsAllocatable(symbol) && - !details.isDummy()) { + !details.isDummy() && !evaluate::IsExplicitShape(symbol)) { messages_.Say( - "Object '%s' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument"_err_en_US, + "Object '%s' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, explicit shape, or a dummy argument"_err_en_US, symbol.name()); } break; @@ -1441,10 +1436,6 @@ void CheckHelper::CheckSubprogram( } if (cudaAttrs && *cudaAttrs != common::CUDASubprogramAttrs::Host) { // CUDA device subprogram checks - if (symbol.attrs().HasAny({Attr::RECURSIVE, Attr::PURE, Attr::ELEMENTAL})) { - messages_.Say(symbol.name(), - "A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL"_err_en_US); - } if (ClassifyProcedure(symbol) == ProcedureDefinitionClass::Internal) { messages_.Say(symbol.name(), "A device subprogram may not be an internal subprogram"_err_en_US); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 56653aa74f0cc55552b86319ade416ccb2748cf4..8a16299db319c27449e530ffe89d893b37926af7 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2471,11 +2471,11 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) { CheckAllowed(llvm::omp::Clause::OMPC_shared); - CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v); + CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED"); } void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) { CheckAllowed(llvm::omp::Clause::OMPC_private); - CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v); + CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE"); CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_private); } @@ -2513,7 +2513,8 @@ bool OmpStructureChecker::IsDataRefTypeParamInquiry( } void OmpStructureChecker::CheckIsVarPartOfAnotherVar( - const parser::CharBlock &source, const parser::OmpObjectList &objList) { + const parser::CharBlock &source, const parser::OmpObjectList &objList, + llvm::StringRef clause) { for (const auto &ompObject : objList.v) { common::visit( common::visitors{ @@ -2539,7 +2540,8 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar( context_.Say(source, "A variable that is part of another variable (as an " "array or structure element) cannot appear in a " - "PRIVATE or SHARED clause"_err_en_US); + "%s clause"_err_en_US, + clause.data()); } } } @@ -2552,6 +2554,8 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar( void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) { CheckAllowed(llvm::omp::Clause::OMPC_firstprivate); + + CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE"); CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v); SymbolSourceMap currSymbols; @@ -2888,6 +2892,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) { CheckAllowed(llvm::omp::Clause::OMPC_lastprivate); + CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "LASTPRIVATE"); + DirectivesClauseTriple dirClauseTriple; SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 8287653458e1cf0439bfaded3f3b2b4f029c40d5..1f7284307703bf6b24408fd8bafb2a7c14b3c03e 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -163,8 +163,8 @@ private: void CheckDependArraySection( const common::Indirection &, const parser::Name &); bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef); - void CheckIsVarPartOfAnotherVar( - const parser::CharBlock &source, const parser::OmpObjectList &objList); + void CheckIsVarPartOfAnotherVar(const parser::CharBlock &source, + const parser::OmpObjectList &objList, llvm::StringRef clause = ""); void CheckThreadprivateOrDeclareTargetVar( const parser::OmpObjectList &objList); void CheckSymbolNames( diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 6af86de9dd81cbd0f7936a52828649c962bb7cf6..a270e4b385e8dbe8b1f7e02350929d801930051f 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2562,7 +2562,8 @@ std::pair ExpressionAnalyzer::ResolveGeneric( } if (std::optional procedure{ characteristics::Procedure::Characterize( - ProcedureDesignator{specific}, context_.foldingContext())}) { + ProcedureDesignator{specific}, context_.foldingContext(), + /*emitError=*/false)}) { ActualArguments localActuals{actuals}; if (specific.has()) { if (!adjustActuals.value()(specific, localActuals)) { @@ -3164,7 +3165,7 @@ std::optional ExpressionAnalyzer::CheckCall( } if (!chars) { chars = characteristics::Procedure::Characterize( - proc, context_.foldingContext()); + proc, context_.foldingContext(), /*emitError=*/true); } bool ok{true}; if (chars) { diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 4b4ce153084d8e7157028a9c8494d1eb9763aeb3..60a496a63cb380a34fdc7dda2e6cc317ad4dce43 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -244,7 +244,8 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef &f) { } else if (const auto *intrinsic{f.proc().GetSpecificIntrinsic()}) { funcName = intrinsic->name; } - auto proc{Procedure::Characterize(f.proc(), foldingContext_)}; + auto proc{ + Procedure::Characterize(f.proc(), foldingContext_, /*emitError=*/true)}; if (!proc) { return false; } @@ -393,7 +394,8 @@ bool PointerAssignmentChecker::Check(const evaluate::ProcedureDesignator &d) { symbol->name()); } } - if (auto chars{Procedure::Characterize(d, foldingContext_)}) { + if (auto chars{ + Procedure::Characterize(d, foldingContext_, /*emitError=*/true)}) { // Disregard the elemental attribute of RHS intrinsics. if (symbol && symbol->GetUltimate().attrs().test(Attr::INTRINSIC)) { chars->attrs.reset(Procedure::Attr::Elemental); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index f4ac7f198d854e4b0664162c21645427ce95ecd9..318687508ff1f5c72846476a6b7cdcd84031fdb8 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2096,15 +2096,10 @@ Symbol *OmpAttributeVisitor::ResolveOmpCommonBlockName( if (!name) { return nullptr; } - // First check if the Common Block is declared in the current scope - if (auto *cur{GetContext().scope.FindCommonBlock(name->source)}) { - name->symbol = cur; - return cur; - } - // Then check parent scope - if (auto *prev{GetContext().scope.parent().FindCommonBlock(name->source)}) { - name->symbol = prev; - return prev; + if (auto *cb{GetProgramUnitOrBlockConstructContaining(GetContext().scope) + .FindCommonBlock(name->source)}) { + name->symbol = cb; + return cb; } return nullptr; } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index f0198cb792280a053ed84f4802cdd91f01e6ce56..b941f257a95ea3d8f4903d5bfef37107231d175f 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -687,7 +687,7 @@ protected: Symbol &, bool respectImplicitNoneType = true); void CheckEntryDummyUse(SourceName, Symbol *); bool ConvertToObjectEntity(Symbol &); - bool ConvertToProcEntity(Symbol &); + bool ConvertToProcEntity(Symbol &, std::optional = std::nullopt); const DeclTypeSpec &MakeNumericType( TypeCategory, const std::optional &); @@ -2253,14 +2253,19 @@ void ScopeHandler::SayWithReason(const parser::Name &name, Symbol &symbol, void ScopeHandler::SayWithDecl( const parser::Name &name, Symbol &symbol, MessageFixedText &&msg) { - bool isFatal{msg.IsFatal()}; - Say(name, std::move(msg), symbol.name()) - .Attach(Message{symbol.name(), - symbol.test(Symbol::Flag::Implicit) - ? "Implicit declaration of '%s'"_en_US - : "Declaration of '%s'"_en_US, - name.source}); - context().SetError(symbol, isFatal); + auto &message{Say(name, std::move(msg), symbol.name()) + .Attach(Message{symbol.name(), + symbol.test(Symbol::Flag::Implicit) + ? "Implicit declaration of '%s'"_en_US + : "Declaration of '%s'"_en_US, + name.source})}; + if (const auto *proc{symbol.detailsIf()}) { + if (auto usedAsProc{proc->usedAsProcedureHere()}) { + if (usedAsProc->begin() != symbol.name().begin()) { + message.Attach(Message{*usedAsProc, "Referenced as a procedure"_en_US}); + } + } + } } void ScopeHandler::SayLocalMustBeVariable( @@ -2659,9 +2664,9 @@ bool ScopeHandler::ConvertToObjectEntity(Symbol &symbol) { return true; } // Convert symbol to be a ProcEntity or return false if it can't be. -bool ScopeHandler::ConvertToProcEntity(Symbol &symbol) { +bool ScopeHandler::ConvertToProcEntity( + Symbol &symbol, std::optional usedHere) { if (symbol.has()) { - // nothing to do } else if (symbol.has()) { symbol.set_details(ProcEntityDetails{}); } else if (auto *details{symbol.detailsIf()}) { @@ -2684,6 +2689,10 @@ bool ScopeHandler::ConvertToProcEntity(Symbol &symbol) { } else { return false; } + auto &proc{symbol.get()}; + if (usedHere && !proc.usedAsProcedureHere()) { + proc.set_usedAsProcedureHere(*usedHere); + } return true; } @@ -3650,7 +3659,7 @@ bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) { misparsedStmtFuncFound_ = true; return false; } - if (DoesScopeContain(&ultimate.owner(), currScope())) { + if (IsHostAssociated(*symbol, currScope())) { if (context().ShouldWarn( common::LanguageFeature::StatementFunctionExtensions)) { Say(name, @@ -4805,7 +4814,7 @@ bool DeclarationVisitor::Pre(const parser::ExternalStmt &x) { HandleAttributeStmt(Attr::EXTERNAL, x.v); for (const auto &name : x.v) { auto *symbol{FindSymbol(name)}; - if (!ConvertToProcEntity(DEREF(symbol))) { + if (!ConvertToProcEntity(DEREF(symbol), name.source)) { // Check if previous symbol is an interface. if (auto *details{symbol->detailsIf()}) { if (details->isInterface()) { @@ -4845,7 +4854,7 @@ void DeclarationVisitor::DeclareIntrinsic(const parser::Name &name) { auto &symbol{DEREF(FindSymbol(name))}; if (symbol.has()) { // Generic interface is extending intrinsic; ok - } else if (!ConvertToProcEntity(symbol)) { + } else if (!ConvertToProcEntity(symbol, name.source)) { SayWithDecl( name, symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US); } else if (symbol.attrs().test(Attr::EXTERNAL)) { // C840 @@ -7705,6 +7714,7 @@ const parser::Name *DeclarationVisitor::ResolveDataRef( } else if (!context().HasError(*name->symbol)) { SayWithDecl(*name, *name->symbol, "Cannot reference function '%s' as data"_err_en_US); + context().SetError(*name->symbol); } } return name; @@ -8119,7 +8129,7 @@ void ResolveNamesVisitor::HandleProcedureName( symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{}); } Resolve(name, *symbol); - ConvertToProcEntity(*symbol); + ConvertToProcEntity(*symbol, name.source); if (!symbol->attrs().test(Attr::INTRINSIC)) { if (CheckImplicitNoneExternal(name.source, *symbol)) { MakeExternal(*symbol); @@ -8144,7 +8154,7 @@ void ResolveNamesVisitor::HandleProcedureName( name.symbol = symbol; } CheckEntryDummyUse(name.source, symbol); - bool convertedToProcEntity{ConvertToProcEntity(*symbol)}; + bool convertedToProcEntity{ConvertToProcEntity(*symbol, name.source)}; if (convertedToProcEntity && !symbol->attrs().test(Attr::EXTERNAL) && IsIntrinsic(symbol->name(), flag) && !IsDummy(*symbol)) { AcquireIntrinsicProcedureFlags(*symbol); @@ -8203,7 +8213,7 @@ void ResolveNamesVisitor::NoteExecutablePartCall( ? Symbol::Flag::Function : Symbol::Flag::Subroutine}; if (!symbol->test(other)) { - ConvertToProcEntity(*symbol); + ConvertToProcEntity(*symbol, name); if (auto *details{symbol->detailsIf()}) { symbol->set(flag); if (IsDummy(*symbol)) { @@ -8240,11 +8250,13 @@ bool ResolveNamesVisitor::SetProcFlag( if (symbol.test(Symbol::Flag::Function) && flag == Symbol::Flag::Subroutine) { SayWithDecl( name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US); + context().SetError(symbol); return false; } else if (symbol.test(Symbol::Flag::Subroutine) && flag == Symbol::Flag::Function) { SayWithDecl( name, symbol, "Cannot call subroutine '%s' like a function"_err_en_US); + context().SetError(symbol); return false; } else if (flag == Symbol::Flag::Function && IsLocallyImplicitGlobalSymbol(symbol, name) && @@ -8263,6 +8275,7 @@ bool ResolveNamesVisitor::SetProcFlag( } else if (symbol.GetType() && flag == Symbol::Flag::Subroutine) { SayWithDecl( name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US); + context().SetError(symbol); } else if (symbol.attrs().test(Attr::INTRINSIC)) { AcquireIntrinsicProcedureFlags(symbol); } @@ -8724,7 +8737,7 @@ bool ResolveNamesVisitor::Pre(const parser::PointerAssignmentStmt &x) { context().globalScope(), name->source, Attrs{Attr::EXTERNAL})}; symbol.implicitAttrs().set(Attr::EXTERNAL); Resolve(*name, symbol); - ConvertToProcEntity(symbol); + ConvertToProcEntity(symbol, name->source); return false; } } diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90 index 3d3dbef6d018aa9b3ddfd8dccbc92ff7417fc434..4746ca20a13a7ece805105f065630e39c7664a93 100644 --- a/flang/module/__fortran_builtins.f90 +++ b/flang/module/__fortran_builtins.f90 @@ -18,6 +18,7 @@ module __fortran_builtins private intrinsic :: __builtin_c_loc + public :: __builtin_c_loc intrinsic :: __builtin_c_f_pointer public :: __builtin_c_f_pointer @@ -56,8 +57,6 @@ module __fortran_builtins integer, parameter, public :: & __builtin_atomic_logical_kind = __builtin_atomic_int_kind - procedure(type(__builtin_c_ptr)), public :: __builtin_c_loc - type, public :: __builtin_dim3 integer :: x=1, y=1, z=1 end type diff --git a/flang/test/Driver/debug-level.f90 b/flang/test/Driver/debug-level.f90 new file mode 100644 index 0000000000000000000000000000000000000000..bc0aee166e6a3736c7c94c430322ec38aa607fa0 --- /dev/null +++ b/flang/test/Driver/debug-level.f90 @@ -0,0 +1,7 @@ +! RUN: %flang %s -g -c -### 2>&1 | FileCheck %s --check-prefix=FULL +! RUN: %flang %s -g1 -c -### 2>&1 | FileCheck %s --check-prefix=LINE +! RUN: %flang %s -gline-tables-only -c -### 2>&1 | FileCheck %s --check-prefix=LINE + +! LINE: -debug-info-kind=line-tables-only +! FULL: -debug-info-kind=standalone + diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 index de2fe3048f993ce3a5e1e45d6ffde6d53cd3c2b9..b5bb0f1c1b25604180097d7d44ddf4299c64257b 100644 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -109,7 +109,7 @@ ! CHECK-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! CHECK-NEXT: --gcc-install-dir= ! CHECK-NEXT: Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation -! CHECK-NEXT: --gcc-toolchain= Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Clang will use the GCC installation with the largest version +! CHECK-NEXT: --gcc-toolchain= Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Flang will use the GCC installation with the largest version ! CHECK-NEXT: -gline-directives-only Emit debug line info directives only ! CHECK-NEXT: -gline-tables-only Emit debug line number tables only ! CHECK-NEXT: -gpulibc Link the LLVM C Library for GPUs diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index b258eb59c1862919baf578fd2987d043660c997e..0b0a493baf07f7e63f291f97ee979c63fd365dbc 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -97,7 +97,7 @@ ! HELP-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! HELP-NEXT: --gcc-install-dir= ! HELP-NEXT: Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation -! HELP-NEXT: --gcc-toolchain= Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Clang will use the GCC installation with the largest version +! HELP-NEXT: --gcc-toolchain= Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Flang will use the GCC installation with the largest version ! HELP-NEXT: -gline-directives-only Emit debug line info directives only ! HELP-NEXT: -gline-tables-only Emit debug line number tables only ! HELP-NEXT: -gpulibc Link the LLVM C Library for GPUs diff --git a/flang/test/Driver/mlir-debug-pass-pipeline.f90 b/flang/test/Driver/mlir-debug-pass-pipeline.f90 index 04d432f854ca35b7fe000da10bafd950c8248cc4..ef84cb80ecf1db05d3daae41414ad4bc0f00c640 100644 --- a/flang/test/Driver/mlir-debug-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-debug-pass-pipeline.f90 @@ -72,11 +72,13 @@ end program ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! ALL-NEXT: BoxedProcedurePass -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction'] ! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOnFuncOpt +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index cfa0de63cde5e819f8303a6319d03859680133a9..d1ff2869b0a6a94d79ab88276197dc7306ae23ff 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -67,11 +67,13 @@ end program ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! ALL-NEXT: BoxedProcedurePass -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction'] ! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOnFuncOpt +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Evaluate/fold-out_of_range.f90 b/flang/test/Evaluate/fold-out_of_range.f90 index de66c803b103e19119b73c0b0b4fe81546ecf61d..30665b9021a9bbcb1652ec03df861b0a56d93840 100644 --- a/flang/test/Evaluate/fold-out_of_range.f90 +++ b/flang/test/Evaluate/fold-out_of_range.f90 @@ -90,35 +90,65 @@ module m logical, parameter :: test_r2r8 = .not. any(out_of_range(r2v, 1._8)) logical, parameter :: test_r2r10 = .not. any(out_of_range(r2v, 1._10)) logical, parameter :: test_r2r16 = .not. any(out_of_range(r2v, 1._16)) - logical, parameter :: test_r3r2 = all(out_of_range(r3v, 1._2) .eqv. finites) + logical, parameter :: test_r3r2 = all(out_of_range(r3v, 1._2) .eqv. finites) + !WARN: warning: invalid argument on REAL(2) to REAL(3) conversion + logical, parameter :: test_r3r2b = .not. any(out_of_range(real(r2v, 3), 1._2)) logical, parameter :: test_r3r3 = .not. any(out_of_range(r3v, 1._3)) logical, parameter :: test_r3r4 = .not. any(out_of_range(r3v, 1._4)) logical, parameter :: test_r3r8 = .not. any(out_of_range(r3v, 1._8)) logical, parameter :: test_r3r10 = .not. any(out_of_range(r3v, 1._10)) logical, parameter :: test_r3r16 = .not. any(out_of_range(r3v, 1._16)) - logical, parameter :: test_r4r2 = all(out_of_range(r4v, 1._2) .eqv. finites) - logical, parameter :: test_r4r3 = all(out_of_range(r4v, 1._3) .eqv. finites) + logical, parameter :: test_r4r2 = all(out_of_range(r4v, 1._2) .eqv. finites) + !WARN: warning: invalid argument on REAL(2) to REAL(4) conversion + logical, parameter :: test_r4r2b = .not. any(out_of_range(real(r2v, 4), 1._2)) + logical, parameter :: test_r4r3 = all(out_of_range(r4v, 1._3) .eqv. finites) + !WARN: warning: invalid argument on REAL(3) to REAL(4) conversion + logical, parameter :: test_r4r3b = .not. any(out_of_range(real(r3v, 4), 1._3)) logical, parameter :: test_r4r4 = .not. any(out_of_range(r4v, 1._4)) logical, parameter :: test_r4r8 = .not. any(out_of_range(r4v, 1._8)) logical, parameter :: test_r4r10 = .not. any(out_of_range(r4v, 1._10)) logical, parameter :: test_r4r16 = .not. any(out_of_range(r4v, 1._16)) - logical, parameter :: test_r8r2 = all(out_of_range(r8v, 1._2) .eqv. finites) - logical, parameter :: test_r8r3 = all(out_of_range(r8v, 1._3) .eqv. finites) - logical, parameter :: test_r8r4 = all(out_of_range(r8v, 1._4) .eqv. finites) + logical, parameter :: test_r8r2 = all(out_of_range(r8v, 1._2) .eqv. finites) + !WARN: warning: invalid argument on REAL(2) to REAL(8) conversion + logical, parameter :: test_r8r2b = .not. any(out_of_range(real(r2v, 8), 1._2)) + logical, parameter :: test_r8r3 = all(out_of_range(r8v, 1._3) .eqv. finites) + !WARN: warning: invalid argument on REAL(3) to REAL(8) conversion + logical, parameter :: test_r8r3b = .not. any(out_of_range(real(r3v, 8), 1._3)) + logical, parameter :: test_r8r4 = all(out_of_range(r8v, 1._4) .eqv. finites) + !WARN: warning: invalid argument on REAL(4) to REAL(8) conversion + logical, parameter :: test_r8r4b = .not. any(out_of_range(real(r4v, 8), 1._4)) logical, parameter :: test_r8r8 = .not. any(out_of_range(r8v, 1._8)) logical, parameter :: test_r8r10 = .not. any(out_of_range(r8v, 1._10)) logical, parameter :: test_r8r16 = .not. any(out_of_range(r8v, 1._16)) - logical, parameter :: test_r10r2 = all(out_of_range(r10v, 1._2) .eqv. finites) - logical, parameter :: test_r10r3 = all(out_of_range(r10v, 1._3) .eqv. finites) - logical, parameter :: test_r10r4 = all(out_of_range(r10v, 1._4) .eqv. finites) - logical, parameter :: test_r10r8 = all(out_of_range(r10v, 1._8) .eqv. finites) + logical, parameter :: test_r10r2 = all(out_of_range(r10v, 1._2) .eqv. finites) + !WARN: warning: invalid argument on REAL(2) to REAL(10) conversion + logical, parameter :: test_r10r2b = .not. any(out_of_range(real(r2v, 10), 1._2)) + logical, parameter :: test_r10r3 = all(out_of_range(r10v, 1._3) .eqv. finites) + !WARN: warning: invalid argument on REAL(3) to REAL(10) conversion + logical, parameter :: test_r10r3b = .not. any(out_of_range(real(r3v, 10), 1._3)) + logical, parameter :: test_r10r4 = all(out_of_range(r10v, 1._4) .eqv. finites) + !WARN: warning: invalid argument on REAL(4) to REAL(10) conversion + logical, parameter :: test_r10r4b = .not. any(out_of_range(real(r4v, 10), 1._4)) + logical, parameter :: test_r10r8 = all(out_of_range(r10v, 1._8) .eqv. finites) + !WARN: warning: invalid argument on REAL(8) to REAL(10) conversion + logical, parameter :: test_r10r8b = .not. any(out_of_range(real(r8v, 10), 1._8)) logical, parameter :: test_r10r10 = .not. any(out_of_range(r10v, 1._10)) logical, parameter :: test_r10r16 = .not. any(out_of_range(r10v, 1._16)) - logical, parameter :: test_r16r2 = all(out_of_range(r16v, 1._2) .eqv. finites) - logical, parameter :: test_r16r3 = all(out_of_range(r16v, 1._3) .eqv. finites) - logical, parameter :: test_r16r4 = all(out_of_range(r16v, 1._4) .eqv. finites) - logical, parameter :: test_r16r8 = all(out_of_range(r16v, 1._8) .eqv. finites) + logical, parameter :: test_r16r2 = all(out_of_range(r16v, 1._2) .eqv. finites) + !WARN: warning: invalid argument on REAL(2) to REAL(16) conversion + logical, parameter :: test_r16r2b = .not. any(out_of_range(real(r2v, 16), 1._2)) + logical, parameter :: test_r16r3 = all(out_of_range(r16v, 1._3) .eqv. finites) + !WARN: warning: invalid argument on REAL(3) to REAL(16) conversion + logical, parameter :: test_r16r3b = .not. any(out_of_range(real(r3v, 16), 1._3)) + logical, parameter :: test_r16r4 = all(out_of_range(r16v, 1._4) .eqv. finites) + !WARN: warning: invalid argument on REAL(4) to REAL(16) conversion + logical, parameter :: test_r16r4b = .not. any(out_of_range(real(r4v, 16), 1._4)) + logical, parameter :: test_r16r8 = all(out_of_range(r16v, 1._8) .eqv. finites) + !WARN: warning: invalid argument on REAL(8) to REAL(16) conversion + logical, parameter :: test_r16r8b = .not. any(out_of_range(real(r8v, 16), 1._8)) logical, parameter :: test_r16r10 = all(out_of_range(r16v, 1._10) .eqv. finites) + !WARN: warning: invalid argument on REAL(10) to REAL(16) conversion + logical, parameter :: test_r16r10b= .not. any(out_of_range(real(r10v, 16), 1._10)) logical, parameter :: test_r16r16 = .not. any(out_of_range(r16v, 1._16)) logical, parameter :: test_r2i1 = all(out_of_range(r2v, 1_1)) @@ -320,4 +350,12 @@ module m logical, parameter :: test_r16i16ur = all(out_of_range(real(i16v, kind=16)+.5_16, 1_16, .true.) .eqv. [.false., .true.]) logical, parameter :: test_r16i16d = all(out_of_range(real(i16v, kind=16)-.5_16, 1_16, .false.) .eqv. [.false., .true.]) logical, parameter :: test_r16i16dr = all(out_of_range(real(i16v, kind=16)-.5_16, 1_16, .true.) .eqv. [.false., .true.]) + + contains + subroutine s(x, r) + real(8), intent(in) :: x + logical, intent(in), optional :: r + !WARN: warning: ROUND= argument to OUT_OF_RANGE() is an optional dummy argument that must be present at execution + print *, out_of_range(x, 1, round=r) + end end diff --git a/flang/test/Evaluate/rewrite-out_of_range.F90 b/flang/test/Evaluate/rewrite-out_of_range.F90 new file mode 100644 index 0000000000000000000000000000000000000000..a5cd09cb2853598b9567175e3e3e62972fe23678 --- /dev/null +++ b/flang/test/Evaluate/rewrite-out_of_range.F90 @@ -0,0 +1,208 @@ +! Tests rewriting of OUT_OF_RANGE() +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s + +logical round + +#define T1(XT,XK,MT,MK) \ +block; \ + XT(XK) x; \ + MT(MK) mold; \ + print *, #XT, XK, #MT, MK, out_of_range(x,mold); \ +end block + +#define T2(XT,XK,MT,MK) \ +block; \ + XT(XK) x; \ + MT(MK) mold; \ + print *, #XT, XK, #MT, MK, 'round', out_of_range(x,mold,round); \ +end block + +#define INTMOLDS(M,XT,XK) \ + M(XT,XK,integer,1); \ + M(XT,XK,integer,2); \ + M(XT,XK,integer,4); \ + M(XT,XK,integer,8); \ + M(XT,XK,integer,16) + +#define REALMOLDS(M,XT,XK) \ + M(XT,XK,real,2); \ + M(XT,XK,real,3); \ + M(XT,XK,real,4); \ + M(XT,XK,real,8); \ + M(XT,XK,real,10); \ + M(XT,XK,real,16) + +#define INTXS(M1,M2) \ + M1(M2, integer, 1); \ + M1(M2, integer, 2); \ + M1(M2, integer, 4); \ + M1(M2, integer, 8); \ + M1(M2, integer, 16) + +#define REALXS(M1,M2) \ + M1(M2, real, 2); \ + M1(M2, real, 3); \ + M1(M2, real, 4); \ + M1(M2, real, 8); \ + M1(M2, real, 10); \ + M1(M2, real, 16) + +INTXS(INTMOLDS, T1) +INTXS(REALMOLDS, T1) +REALXS(INTMOLDS, T1) +REALXS(INTMOLDS, T2) +REALXS(REALMOLDS, T1) + +end + +!CHECK: PRINT *, " integer", 1_4, "integer", 1_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "integer", 2_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "integer", 4_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "integer", 8_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "integer", 16_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "integer", 1_4, bgt(x+128_2,255_2) +!CHECK: PRINT *, " integer", 2_4, "integer", 2_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "integer", 4_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "integer", 8_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "integer", 16_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "integer", 1_4, bgt(x+128_4,255_4) +!CHECK: PRINT *, " integer", 4_4, "integer", 2_4, bgt(x+32768_4,65535_4) +!CHECK: PRINT *, " integer", 4_4, "integer", 4_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "integer", 8_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "integer", 16_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "integer", 1_4, bgt(x+128_8,255_8) +!CHECK: PRINT *, " integer", 8_4, "integer", 2_4, bgt(x+32768_8,65535_8) +!CHECK: PRINT *, " integer", 8_4, "integer", 4_4, bgt(x+2147483648_8,4294967295_8) +!CHECK: PRINT *, " integer", 8_4, "integer", 8_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "integer", 16_4, .false._4 +!CHECK: PRINT *, " integer", 16_4, "integer", 1_4, bgt(x+128_16,255_16) +!CHECK: PRINT *, " integer", 16_4, "integer", 2_4, bgt(x+32768_16,65535_16) +!CHECK: PRINT *, " integer", 16_4, "integer", 4_4, bgt(x+2147483648_16,4294967295_16) +!CHECK: PRINT *, " integer", 16_4, "integer", 8_4, bgt(x+9223372036854775808_16,18446744073709551615_16) +!CHECK: PRINT *, " integer", 16_4, "integer", 16_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "real", 2_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " integer", 1_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "real", 2_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " integer", 2_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "real", 2_4, bgt(x--65519_4,131038_4) +!CHECK: PRINT *, " integer", 4_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " integer", 4_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "real", 2_4, bgt(x--65519_8,131038_8) +!CHECK: PRINT *, " integer", 8_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " integer", 8_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " integer", 16_4, "real", 2_4, bgt(x--65519_16,131038_16) +!CHECK: PRINT *, " integer", 16_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " integer", 16_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " integer", 16_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " integer", 16_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " integer", 16_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " real", 2_4, "integer", 1_4, bgt(transfer(real(x,kind=4)--1.28875e2_4,0_4),1132488704_4) +!CHECK: PRINT *, " real", 2_4, "integer", 2_4, bgt(transfer(real(x,kind=4)--3.2768e4_4,0_4),1199566848_4) +!CHECK: PRINT *, " real", 2_4, "integer", 4_4, bgt(transfer(real(x,kind=4)--6.5504e4_4,0_4),1207951360_4) +!CHECK: PRINT *, " real", 2_4, "integer", 8_4, bgt(transfer(real(x,kind=4)--6.5504e4_4,0_4),1207951360_4) +!CHECK: PRINT *, " real", 2_4, "integer", 16_4, bgt(transfer(real(x,kind=4)--6.5504e4_4,0_4),1207951360_4) +!CHECK: PRINT *, " real", 3_4, "integer", 1_4, bgt(transfer(real(x,kind=4)--1.28e2_4,0_4),1132429312_4) +!CHECK: PRINT *, " real", 3_4, "integer", 2_4, bgt(transfer(real(x,kind=4)--3.2768e4_4,0_4),1199538176_4) +!CHECK: PRINT *, " real", 3_4, "integer", 4_4, bgt(transfer(real(x,kind=4)--2.147483648e9_4,0_4),1333755904_4) +!CHECK: PRINT *, " real", 3_4, "integer", 8_4, bgt(transfer(real(x,kind=4)--9.223372036854775808e18_4,0_4),1602191360_4) +!CHECK: PRINT *, " real", 3_4, "integer", 16_4, bgt(transfer(real(x,kind=4)--1.70141183460469231731687303715884105728e38_4,0_4),2139062272_4) +!CHECK: PRINT *, " real", 4_4, "integer", 1_4, bgt(transfer(real(x,kind=8)--1.289999847412109375e2_8,0_8),4643228807602372608_8) +!CHECK: PRINT *, " real", 4_4, "integer", 2_4, bgt(transfer(real(x,kind=8)--3.276899609375e4_8,0_8),4679240081154768896_8) +!CHECK: PRINT *, " real", 4_4, "integer", 4_4, bgt(transfer(real(x,kind=8)--2.147483648e9_8,0_8),4751297606607437824_8) +!CHECK: PRINT *, " real", 4_4, "integer", 8_4, bgt(transfer(real(x,kind=8)--9.223372036854775808e18_8,0_8),4895412794683293696_8) +!CHECK: PRINT *, " real", 4_4, "integer", 16_4, bgt(transfer(real(x,kind=8)--1.70141183460469231731687303715884105728e38_8,0_8),5183643170835005440_8) +!CHECK: PRINT *, " real", 8_4, "integer", 1_4, bgt(transfer(real(x,kind=16)--1.28999999999999971578290569595992565155029296875e2_16,0_16),85106958090653963310049098151042744320_16) +!CHECK: PRINT *, " real", 8_4, "integer", 2_4, bgt(transfer(real(x,kind=16)--3.27689999999999927240423858165740966796875e4_16,0_16),85148476262340800793671255767969169408_16) +!CHECK: PRINT *, " real", 8_4, "integer", 4_4, bgt(transfer(real(x,kind=16)--2.147483648999999523162841796875e9_16,0_16),85231552932850404447283020744867446784_16) +!CHECK: PRINT *, " real", 8_4, "integer", 8_4, bgt(transfer(real(x,kind=16)--9.223372036854775808e18_16,0_16),85397706432322310005864612374379495424_16) +!CHECK: PRINT *, " real", 8_4, "integer", 16_4, bgt(transfer(real(x,kind=16)--1.70141183460469231731687303715884105728e38_16,0_16),85730013431268538974090564139449581568_16) +!CHECK: PRINT *, " real", 10_4, "integer", 1_4, bgt(transfer(real(x,kind=16)--1.2899999999999999998612221219218554324470460414886474609375e2_16,0_16),85106958090653963310913367067032813568_16) +!CHECK: PRINT *, " real", 10_4, "integer", 2_4, bgt(transfer(real(x,kind=16)--3.2768999999999999996447286321199499070644378662109375e4_16,0_16),85148476262340800794535524683959238656_16) +!CHECK: PRINT *, " real", 10_4, "integer", 4_4, bgt(transfer(real(x,kind=16)--2.14748364899999999976716935634613037109375e9_16,0_16),85231552932850404448147289660857516032_16) +!CHECK: PRINT *, " real", 10_4, "integer", 8_4, bgt(transfer(real(x,kind=16)--9.223372036854775808e18_16,0_16),85397706432322310006440791651706208256_16) +!CHECK: PRINT *, " real", 10_4, "integer", 16_4, bgt(transfer(real(x,kind=16)--1.70141183460469231731687303715884105728e38_16,0_16),85730013431268538974666743416776294400_16) +!CHECK: PRINT *, " real", 16_4, "integer", 1_4, bgt(transfer(x--1.28999999999999999999999999999999975348096711843381080883482334912930322712298902843031100928783416748046875e2_16,0_16),85106958090653963310913789279497879551_16) +!CHECK: PRINT *, " real", 16_4, "integer", 2_4, bgt(transfer(x--3.27689999999999999999999999999999936891127582319055567061714777377101626143485191278159618377685546875e4_16,0_16),85148476262340800794535946896424304639_16) +!CHECK: PRINT *, " real", 16_4, "integer", 4_4, bgt(transfer(x--2.147483648999999999999999999999999586409693723486162564295653965018573217093944549560546875e9_16,0_16),85231552932850404448147711873322582015_16) +!CHECK: PRINT *, " real", 16_4, "integer", 8_4, bgt(transfer(x--9.2233720368547758089999999999999982236431605997495353221893310546875e18_16,0_16),85397706432322310006441354601659629567_16) +!CHECK: PRINT *, " real", 16_4, "integer", 16_4, bgt(transfer(x--1.70141183460469231731687303715884105728e38_16,0_16),85730013431268538974667024891753005055_16) +!CHECK: PRINT *, " real", 2_4, "integer", 1_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-1.28375e2_2,-1.28875e2_2,round),kind=4),0_4),transfer(real(merge(1.274375e2_2,1.279375e2_2,round),kind=4)-real(merge(-1.28375e2_2,-1.28875e2_2,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 2_4, "integer", 2_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-3.2768e4_2,-3.2768e4_2,round),kind=4),0_4),transfer(real(merge(3.2752e4_2,3.2752e4_2,round),kind=4)-real(merge(-3.2768e4_2,-3.2768e4_2,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 2_4, "integer", 4_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-6.5504e4_2,-6.5504e4_2,round),kind=4),0_4),transfer(real(merge(6.5504e4_2,6.5504e4_2,round),kind=4)-real(merge(-6.5504e4_2,-6.5504e4_2,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 2_4, "integer", 8_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-6.5504e4_2,-6.5504e4_2,round),kind=4),0_4),transfer(real(merge(6.5504e4_2,6.5504e4_2,round),kind=4)-real(merge(-6.5504e4_2,-6.5504e4_2,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 2_4, "integer", 16_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-6.5504e4_2,-6.5504e4_2,round),kind=4),0_4),transfer(real(merge(6.5504e4_2,6.5504e4_2,round),kind=4)-real(merge(-6.5504e4_2,-6.5504e4_2,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 3_4, "integer", 1_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-1.28e2_3,-1.28e2_3,round),kind=4),0_4),transfer(real(merge(1.27e2_3,1.275e2_3,round),kind=4)-real(merge(-1.28e2_3,-1.28e2_3,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 3_4, "integer", 2_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-3.2768e4_3,-3.2768e4_3,round),kind=4),0_4),transfer(real(merge(3.264e4_3,3.264e4_3,round),kind=4)-real(merge(-3.2768e4_3,-3.2768e4_3,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 3_4, "integer", 4_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-2.147483648e9_3,-2.147483648e9_3,round),kind=4),0_4),transfer(real(merge(2.13909504e9_3,2.13909504e9_3,round),kind=4)-real(merge(-2.147483648e9_3,-2.147483648e9_3,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 3_4, "integer", 8_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-9.223372036854775808e18_3,-9.223372036854775808e18_3,round),kind=4),0_4),transfer(real(merge(9.18734323983581184e18_3,9.18734323983581184e18_3,round),kind=4)-real(merge(-9.223372036854775808e18_3,-9.223372036854775808e18_3,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 3_4, "integer", 16_4, "round", bgt(transfer(real(x,kind=4)-real(merge(-1.70141183460469231731687303715884105728e38_3,-1.70141183460469231731687303715884105728e38_3,round),kind=4),0_4),transfer(real(merge(1.6947656946257677379523540018574393344e38_3,1.6947656946257677379523540018574393344e38_3,round),kind=4)-real(merge(-1.70141183460469231731687303715884105728e38_3,-1.70141183460469231731687303715884105728e38_3,round),kind=4),0_4)) +!CHECK: PRINT *, " real", 4_4, "integer", 1_4, "round", bgt(transfer(real(x,kind=8)-real(merge(-1.284999847412109375e2_4,-1.289999847412109375e2_4,round),kind=8),0_8),transfer(real(merge(1.2749999237060546875e2_4,1.2799999237060546875e2_4,round),kind=8)-real(merge(-1.284999847412109375e2_4,-1.289999847412109375e2_4,round),kind=8),0_8)) +!CHECK: PRINT *, " real", 4_4, "integer", 2_4, "round", bgt(transfer(real(x,kind=8)-real(merge(-3.276849609375e4_4,-3.276899609375e4_4,round),kind=8),0_8),transfer(real(merge(3.2767498046875e4_4,3.2767998046875e4_4,round),kind=8)-real(merge(-3.276849609375e4_4,-3.276899609375e4_4,round),kind=8),0_8)) +!CHECK: PRINT *, " real", 4_4, "integer", 4_4, "round", bgt(transfer(real(x,kind=8)-real(merge(-2.147483648e9_4,-2.147483648e9_4,round),kind=8),0_8),transfer(real(merge(2.14748352e9_4,2.14748352e9_4,round),kind=8)-real(merge(-2.147483648e9_4,-2.147483648e9_4,round),kind=8),0_8)) +!CHECK: PRINT *, " real", 4_4, "integer", 8_4, "round", bgt(transfer(real(x,kind=8)-real(merge(-9.223372036854775808e18_4,-9.223372036854775808e18_4,round),kind=8),0_8),transfer(real(merge(9.22337148709896192e18_4,9.22337148709896192e18_4,round),kind=8)-real(merge(-9.223372036854775808e18_4,-9.223372036854775808e18_4,round),kind=8),0_8)) +!CHECK: PRINT *, " real", 4_4, "integer", 16_4, "round", bgt(transfer(real(x,kind=8)-real(merge(-1.70141183460469231731687303715884105728e38_4,-1.70141183460469231731687303715884105728e38_4,round),kind=8),0_8),transfer(real(merge(1.7014117331926442990585209174225846272e38_4,1.7014117331926442990585209174225846272e38_4,round),kind=8)-real(merge(-1.70141183460469231731687303715884105728e38_4,-1.70141183460469231731687303715884105728e38_4,round),kind=8),0_8)) +!CHECK: PRINT *, " real", 8_4, "integer", 1_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-1.28499999999999971578290569595992565155029296875e2_8,-1.28999999999999971578290569595992565155029296875e2_8,round),kind=16),0_16),transfer(real(merge(1.274999999999999857891452847979962825775146484375e2_8,1.279999999999999857891452847979962825775146484375e2_8,round),kind=16)-real(merge(-1.28499999999999971578290569595992565155029296875e2_8,-1.28999999999999971578290569595992565155029296875e2_8,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 8_4, "integer", 2_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-3.27684999999999927240423858165740966796875e4_8,-3.27689999999999927240423858165740966796875e4_8,round),kind=16),0_16),transfer(real(merge(3.276749999999999636202119290828704833984375e4_8,3.276799999999999636202119290828704833984375e4_8,round),kind=16)-real(merge(-3.27684999999999927240423858165740966796875e4_8,-3.27689999999999927240423858165740966796875e4_8,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 8_4, "integer", 4_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-2.147483648499999523162841796875e9_8,-2.147483648999999523162841796875e9_8,round),kind=16),0_16),transfer(real(merge(2.1474836474999997615814208984375e9_8,2.1474836479999997615814208984375e9_8,round),kind=16)-real(merge(-2.147483648499999523162841796875e9_8,-2.147483648999999523162841796875e9_8,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 8_4, "integer", 8_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-9.223372036854775808e18_8,-9.223372036854775808e18_8,round),kind=16),0_16),transfer(real(merge(9.223372036854774784e18_8,9.223372036854774784e18_8,round),kind=16)-real(merge(-9.223372036854775808e18_8,-9.223372036854775808e18_8,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 8_4, "integer", 16_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-1.70141183460469231731687303715884105728e38_8,-1.70141183460469231731687303715884105728e38_8,round),kind=16),0_16),transfer(real(merge(1.70141183460469212842221372237303250944e38_8,1.70141183460469212842221372237303250944e38_8,round),kind=16)-real(merge(-1.70141183460469231731687303715884105728e38_8,-1.70141183460469231731687303715884105728e38_8,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 10_4, "integer", 1_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-1.2849999999999999998612221219218554324470460414886474609375e2_10,-1.2899999999999999998612221219218554324470460414886474609375e2_10,round),kind=16),0_16),transfer(real(merge(1.27499999999999999993061106096092771622352302074432373046875e2_10,1.27999999999999999993061106096092771622352302074432373046875e2_10,round),kind=16)-real(merge(-1.2849999999999999998612221219218554324470460414886474609375e2_10,-1.2899999999999999998612221219218554324470460414886474609375e2_10,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 10_4, "integer", 2_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-3.2768499999999999996447286321199499070644378662109375e4_10,-3.2768999999999999996447286321199499070644378662109375e4_10,round),kind=16),0_16),transfer(real(merge(3.27674999999999999982236431605997495353221893310546875e4_10,3.27679999999999999982236431605997495353221893310546875e4_10,round),kind=16)-real(merge(-3.2768499999999999996447286321199499070644378662109375e4_10,-3.2768999999999999996447286321199499070644378662109375e4_10,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 10_4, "integer", 4_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-2.14748364849999999976716935634613037109375e9_10,-2.14748364899999999976716935634613037109375e9_10,round),kind=16),0_16),transfer(real(merge(2.147483647499999999883584678173065185546875e9_10,2.147483647999999999883584678173065185546875e9_10,round),kind=16)-real(merge(-2.14748364849999999976716935634613037109375e9_10,-2.14748364899999999976716935634613037109375e9_10,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 10_4, "integer", 8_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-9.223372036854775808e18_10,-9.223372036854775808e18_10,round),kind=16),0_16),transfer(real(merge(9.223372036854775807e18_10,9.2233720368547758075e18_10,round),kind=16)-real(merge(-9.223372036854775808e18_10,-9.223372036854775808e18_10,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 10_4, "integer", 16_4, "round", bgt(transfer(real(x,kind=16)-real(merge(-1.70141183460469231731687303715884105728e38_10,-1.70141183460469231731687303715884105728e38_10,round),kind=16),0_16),transfer(real(merge(1.7014118346046923172246393167902932992e38_10,1.7014118346046923172246393167902932992e38_10,round),kind=16)-real(merge(-1.70141183460469231731687303715884105728e38_10,-1.70141183460469231731687303715884105728e38_10,round),kind=16),0_16)) +!CHECK: PRINT *, " real", 16_4, "integer", 1_4, "round", bgt(transfer(x-merge(-1.28499999999999999999999999999999975348096711843381080883482334912930322712298902843031100928783416748046875e2_16,-1.28999999999999999999999999999999975348096711843381080883482334912930322712298902843031100928783416748046875e2_16,round),0_16),transfer(merge(1.274999999999999999999999999999999876740483559216905404417411674564651613561494514215155504643917083740234375e2_16,1.279999999999999999999999999999999876740483559216905404417411674564651613561494514215155504643917083740234375e2_16,round)-merge(-1.28499999999999999999999999999999975348096711843381080883482334912930322712298902843031100928783416748046875e2_16,-1.28999999999999999999999999999999975348096711843381080883482334912930322712298902843031100928783416748046875e2_16,round),0_16)) +!CHECK: PRINT *, " real", 16_4, "integer", 2_4, "round", bgt(transfer(x-merge(-3.27684999999999999999999999999999936891127582319055567061714777377101626143485191278159618377685546875e4_16,-3.27689999999999999999999999999999936891127582319055567061714777377101626143485191278159618377685546875e4_16,round),0_16),transfer(merge(3.276749999999999999999999999999999684455637911595277835308573886885508130717425956390798091888427734375e4_16,3.276799999999999999999999999999999684455637911595277835308573886885508130717425956390798091888427734375e4_16,round)-merge(-3.27684999999999999999999999999999936891127582319055567061714777377101626143485191278159618377685546875e4_16,-3.27689999999999999999999999999999936891127582319055567061714777377101626143485191278159618377685546875e4_16,round),0_16)) +!CHECK: PRINT *, " real", 16_4, "integer", 4_4, "round", bgt(transfer(x-merge(-2.147483648499999999999999999999999586409693723486162564295653965018573217093944549560546875e9_16,-2.147483648999999999999999999999999586409693723486162564295653965018573217093944549560546875e9_16,round),0_16),transfer(merge(2.1474836474999999999999999999999997932048468617430812821478269825092866085469722747802734375e9_16,2.1474836479999999999999999999999997932048468617430812821478269825092866085469722747802734375e9_16,round)-merge(-2.147483648499999999999999999999999586409693723486162564295653965018573217093944549560546875e9_16,-2.147483648999999999999999999999999586409693723486162564295653965018573217093944549560546875e9_16,round),0_16)) +!CHECK: PRINT *, " real", 16_4, "integer", 8_4, "round", bgt(transfer(x-merge(-9.2233720368547758084999999999999982236431605997495353221893310546875e18_16,-9.2233720368547758089999999999999982236431605997495353221893310546875e18_16,round),0_16),transfer(merge(9.22337203685477580749999999999999911182158029987476766109466552734375e18_16,9.22337203685477580799999999999999911182158029987476766109466552734375e18_16,round)-merge(-9.2233720368547758084999999999999982236431605997495353221893310546875e18_16,-9.2233720368547758089999999999999982236431605997495353221893310546875e18_16,round),0_16)) +!CHECK: PRINT *, " real", 16_4, "integer", 16_4, "round", bgt(transfer(x-merge(-1.70141183460469231731687303715884105728e38_16,-1.70141183460469231731687303715884105728e38_16,round),0_16),transfer(merge(1.70141183460469231731687303715884089344e38_16,1.70141183460469231731687303715884089344e38_16,round)-merge(-1.70141183460469231731687303715884105728e38_16,-1.70141183460469231731687303715884105728e38_16,round),0_16)) +!CHECK: PRINT *, " real", 2_4, "real", 2_4, .false._4 +!CHECK: PRINT *, " real", 2_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " real", 2_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " real", 2_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " real", 2_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " real", 2_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " real", 3_4, "real", 2_4, blt(int(transfer(abs(x)-6.5536e4_3,0_2),kind=8)-1_8,32639_2) +!CHECK: PRINT *, " real", 3_4, "real", 3_4, .false._4 +!CHECK: PRINT *, " real", 3_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " real", 3_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " real", 3_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " real", 3_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " real", 4_4, "real", 2_4, blt(int(transfer(abs(x)-6.5504e4_4,0_4),kind=8)-1_8,2139095039_4) +!CHECK: PRINT *, " real", 4_4, "real", 3_4, blt(int(transfer(abs(x)-3.3895313892515354759047080037148786688e38_4,0_4),kind=8)-1_8,2139095039_4) +!CHECK: PRINT *, " real", 4_4, "real", 4_4, .false._4 +!CHECK: PRINT *, " real", 4_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " real", 4_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " real", 4_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " real", 8_4, "real", 2_4, blt(transfer(abs(x)-6.5504e4_8,0_8)-1_8,9218868437227405311_8) +!CHECK: PRINT *, " real", 8_4, "real", 3_4, blt(transfer(abs(x)-3.3895313892515354759047080037148786688e38_8,0_8)-1_8,9218868437227405311_8) +!CHECK: PRINT *, " real", 8_4, "real", 4_4, blt(transfer(abs(x)-3.4028234663852885981170418348451692544e38_8,0_8)-1_8,9218868437227405311_8) +!CHECK: PRINT *, " real", 8_4, "real", 8_4, .false._4 +!CHECK: PRINT *, " real", 8_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " real", 8_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " real", 10_4, "real", 2_4, blt(transfer(abs(x)-6.5504e4_10,0_16)-1_16,604444463063240877801471_16) +!CHECK: PRINT *, " real", 10_4, "real", 3_4, blt(transfer(abs(x)-3.3895313892515354759047080037148786688e38_10,0_16)-1_16,604444463063240877801471_16) +!CHECK: PRINT *, " real", 10_4, "real", 4_4, blt(transfer(abs(x)-3.4028234663852885981170418348451692544e38_10,0_16)-1_16,604444463063240877801471_16) +!CHECK: PRINT *, " real", 10_4, "real", 8_4, blt(transfer(abs(x)-1.79769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368e308_10,0_16)-1_16,604444463063240877801471_16) +!CHECK: PRINT *, " real", 10_4, "real", 10_4, .false._4 +!CHECK: PRINT *, " real", 10_4, "real", 16_4, .false._4 +!CHECK: PRINT *, " real", 16_4, "real", 2_4, blt(transfer(abs(x)-6.5504e4_16,0_16)-1_16,170135991163610696904058773219554885631_16) +!CHECK: PRINT *, " real", 16_4, "real", 3_4, blt(transfer(abs(x)-3.3895313892515354759047080037148786688e38_16,0_16)-1_16,170135991163610696904058773219554885631_16) +!CHECK: PRINT *, " real", 16_4, "real", 4_4, blt(transfer(abs(x)-3.4028234663852885981170418348451692544e38_16,0_16)-1_16,170135991163610696904058773219554885631_16) +!CHECK: PRINT *, " real", 16_4, "real", 8_4, blt(transfer(abs(x)-1.79769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368e308_16,0_16)-1_16,170135991163610696904058773219554885631_16) +!CHECK: PRINT *, " real", 16_4, "real", 10_4, blt(transfer(abs(x)-1.18973149535723176502126385303097020516906332229462420044032373389173700552297072261641029033652888285354569780749557731442744315367028843419812557385374367867359320070697326320191591828296152436552951064679108661431179063216977883889613478656060039914875343321145491116008867984515486651285234014977303760000912547939396622315138362241783854274391783813871780588948754057516822634765923557697480511372564902088485522249479139937758502601177354918009979622602685950855888360815984690023564513234659447638493985927645628457966177293040780660922910271504608538808795932778162298682754783076808004015069494230341172895777710033571401055977524212405734700738625166011082837911962300846927720096515350020847447079244384854591288672300061908512647211195136146752763351956292759795725027800298079590419313960302147099703527646744553092202267965628099149823208332964124103850923918473478612192169721054348428704835340811304257300221642134891734717423480071488075100206439051723424765600472176809648610799494341570347632064355862420744350442438056613601760883747816538902780957697597728686007148702828795556714140463261583262360276289631617397848425448686060994827086796804807870251185893083854658422304090880599629459458620190376604844679092600222541053077590106576067134720012584640695703025713896098375799892695455305236856075868317922311363951946885088077187210470520395758748001314313144425494391994017575316933939236688185618912993172910425292123683515992232205099800167710278403536014082929639811512287776813570604578934353545169653956125404884644716978689321167108722908808277835051822885764606221873970285165508372099234948333443522898475123275372663606621390228126470623407535207172405866507951821730346378263135339370677490195019784169044182473806316282858685774143258116536404021840272491339332094921949842244273042701987304453662035026238695780468200360144729199712309553005720614186697485284685618651483271597448120312194675168637934309618961510733006555242148519520176285859509105183947250286387163249416761380499631979144187025430270675849519200883791516940158174004671147787720145964446117520405945350476472180797576111172084627363927960033967047003761337450955318415007379641260504792325166135484129188421134082301547330475406707281876350361733290800595189632520707167390454777712968226520622565143991937680440029238090311243791261477625596469422198137514696707944687035800439250765945161837981185939204954403611491531078225107269148697980924094677214272701240437718740921675661363493890045123235166814608932240069799317601780533819184998193300841098599393876029260139091141452600372028487213241195542428210183120421610446740462163533690058366460659115629876474552506814500393294140413149540067760295100596225302282300363147382468105964844244132486457313743759509641616804802412935187620466813563687753281467553879887177183651289394719533506188500326760735438867336800207438784965701457609034985757124304510203873049485425670247933932280911052604153852899484920399109194612991249163328991799809438033787952209313146694614970593966415237594928589096048991612194498998638483702248667224914892467841020618336462741696957630763248023558797524525373703543388296086275342774001633343405508353704850737454481975472222897528108302089868263302028525992308416805453968791141829762998896457648276528750456285492426516521775079951625966922911497778896235667095662713848201819134832168799586365263762097828507009933729439678463987902491451422274252700636394232799848397673998715441855420156224415492665301451550468548925862027608576183712976335876121538256512963353814166394951655600026415918655485005705261143195291991880795452239464962763563017858089669222640623538289853586759599064700838568712381032959192649484625076899225841930548076362021508902214922052806984201835084058693849381549890944546197789302911357651677540623227829831403347327660395223160342282471752818181884430488092132193355086987339586127607367086665237555567580317149010847732009642431878007000879734603290627894355374356444885190719161645514115576193939969076741515640282654366402676009508752394550734155613586793306603174472092444651353236664764973540085196704077110364053815007348689179836404957060618953500508984091382686953509006678332447257871219660441528492484004185093281190896363417573989716659600075948780061916409485433875852065711654107226099628815012314437794400874930194474433078438899570184271000480830501217712356062289507626904285680004771889315808935851559386317665294808903126774702966254511086154895839508779675546413794489596052797520987481383976257859210575628440175934932416214833956535018919681138909184379573470326940634289008780584694035245347939808067427323629788710086717580253156130235606487870925986528841635097252953709111431720488774740553905400942537542411931794417513706468964386151771884986701034153254238591108962471088538580868883777725864856414593426212108664758848926003176234596076950884914966244415660441955208681198977024e4932_16,0_16)-1_16,170135991163610696904058773219554885631_16) +!CHECK: PRINT *, " real", 16_4, "real", 16_4, .false._4 diff --git a/flang/test/Fir/abstract-result-2.fir b/flang/test/Fir/abstract-result-2.fir index 08b723b83059369191f0028c6f110284ea27a080..af13d57476e8c0722efb382f376a75219251194f 100644 --- a/flang/test/Fir/abstract-result-2.fir +++ b/flang/test/Fir/abstract-result-2.fir @@ -1,4 +1,4 @@ -// RUN: fir-opt %s --abstract-result-on-func-opt | FileCheck %s +// RUN: fir-opt %s --abstract-result | FileCheck %s // Check that the attributes are shifted along with their corresponding arguments diff --git a/flang/test/Fir/abstract-results.fir b/flang/test/Fir/abstract-results.fir index 42ff2a5c8eb2a87c8dee3024bfa2861e23c95057..82f1cd33073fd3a6d88e641228aa36bfcaafc578 100644 --- a/flang/test/Fir/abstract-results.fir +++ b/flang/test/Fir/abstract-results.fir @@ -1,10 +1,10 @@ // Test rewrite of functions that return fir.array<>, fir.type<>, fir.box<> to // functions that take an additional argument for the result. -// RUN: fir-opt %s --abstract-result-on-func-opt | FileCheck %s --check-prefix=FUNC-REF -// RUN: fir-opt %s --abstract-result-on-func-opt=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX -// RUN: fir-opt %s --abstract-result-on-global-opt | FileCheck %s --check-prefix=GLOBAL-REF -// RUN: fir-opt %s --abstract-result-on-global-opt=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX +// RUN: fir-opt %s --abstract-result | FileCheck %s --check-prefix=FUNC-REF +// RUN: fir-opt %s --abstract-result=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX +// RUN: fir-opt %s --abstract-result | FileCheck %s --check-prefix=GLOBAL-REF +// RUN: fir-opt %s --abstract-result=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX // ----------------------- Test declaration rewrite ---------------------------- diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index 80d3520bc7f7d401bb3657bed82a4ec38848a3e0..28c597fc918cd7a2c5ea05e04f9dc9917d1dea6e 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -74,11 +74,13 @@ func.func @_QQmain() { // PASSES-NEXT: (S) 0 num-dce'd - Number of operations DCE'd // PASSES-NEXT: BoxedProcedurePass -// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction'] // PASSES-NEXT: 'fir.global' Pipeline -// PASSES-NEXT: AbstractResultOnGlobalOpt +// PASSES-NEXT: AbstractResultOpt // PASSES-NEXT: 'func.func' Pipeline -// PASSES-NEXT: AbstractResultOnFuncOpt +// PASSES-NEXT: AbstractResultOpt +// PASSES-NEXT: 'omp.declare_reduction' Pipeline +// PASSES-NEXT: AbstractResultOpt // PASSES-NEXT: CodeGenRewrite // PASSES-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Fir/non-trivial-procedure-binding-description.f90 b/flang/test/Fir/non-trivial-procedure-binding-description.f90 index 695d7fdfe232d30a49a655d8da2a1188f740a5e2..668928600157b1510c2e0d635bed533d70d03c5a 100644 --- a/flang/test/Fir/non-trivial-procedure-binding-description.f90 +++ b/flang/test/Fir/non-trivial-procedure-binding-description.f90 @@ -1,5 +1,5 @@ ! RUN: %flang_fc1 -emit-mlir %s -o - | FileCheck %s --check-prefix=BEFORE -! RUN: %flang_fc1 -emit-mlir %s -o - | fir-opt --abstract-result-on-global-opt | FileCheck %s --check-prefix=AFTER +! RUN: %flang_fc1 -emit-mlir %s -o - | fir-opt --abstract-result | FileCheck %s --check-prefix=AFTER module a type f contains diff --git a/flang/test/Lower/CUDA/cuda-allocatable.cuf b/flang/test/Lower/CUDA/cuda-allocatable.cuf index 5b10334ecdbc14c7cb79a5918b7d8879daa412a8..251ff16a56c797cf02c38e29bdccc2ad62dfa79e 100644 --- a/flang/test/Lower/CUDA/cuda-allocatable.cuf +++ b/flang/test/Lower/CUDA/cuda-allocatable.cuf @@ -52,19 +52,19 @@ end subroutine ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> pinned(%[[PLOG_DECL]]#1 : !fir.ref>) {cuda_attr = #fir.cuda} -> i32 subroutine sub4() - real, allocatable, unified :: a(:) + real, allocatable, device :: a(:) integer :: istream allocate(a(10), stream=istream) end subroutine ! CHECK-LABEL: func.func @_QPsub4() ! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub4Ea"} -! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %0 {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub4Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %0 {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub4Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) ! CHECK: %[[ISTREAM:.*]] = fir.alloca i32 {bindc_name = "istream", uniq_name = "_QFsub4Eistream"} ! CHECK: %[[ISTREAM_DECL:.*]]:2 = hlfir.declare %[[ISTREAM]] {uniq_name = "_QFsub4Eistream"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.call @_FortranAAllocatableSetBounds ! CHECK: %[[STREAM:.*]] = fir.load %[[ISTREAM_DECL]]#0 : !fir.ref -! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> stream(%[[STREAM]] : i32) {cuda_attr = #fir.cuda} -> i32 +! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> stream(%[[STREAM]] : i32) {cuda_attr = #fir.cuda} -> i32 subroutine sub5() real, allocatable, device :: a(:) diff --git a/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf b/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf index 6179e609db383c6b6c1037e4d9435baf2f81f0d5..9b728cd19eb552b50d7bb689a34214543cbfa675 100644 --- a/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf +++ b/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf @@ -1,4 +1,5 @@ ! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir -fcuda %s -o - | fir-opt | FileCheck %s ! Test lowering of CUDA kernel loop directive. diff --git a/flang/test/Lower/HLFIR/calls-f77.f90 b/flang/test/Lower/HLFIR/calls-f77.f90 index ac5be007eb838c839d372a69269f7627a819edb4..cefe379a45d353a92dfe242f367b4c62c61847c8 100644 --- a/flang/test/Lower/HLFIR/calls-f77.f90 +++ b/flang/test/Lower/HLFIR/calls-f77.f90 @@ -186,3 +186,16 @@ subroutine alternate_return_call(n1, n2, k) ! CHECK: ^[[block2]]: // pred: ^bb0 7 k = 1; return end + +! ----------------------------------------------------------------------------- +! Test calls to user procedures with intrinsic interfaces +! ----------------------------------------------------------------------------- + +! CHECK-NAME: func.func @_QPintrinsic_iface() +subroutine intrinsic_iface() + intrinsic acos + real :: x + procedure(acos) :: proc + x = proc(1.0) +end subroutine +! CHECK" fir.call @_QPproc(%{{.*}}) {{.*}}: (!fir.ref) -> f32 diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 index f0979ab95f568ad49bd20b216586e03e9e70996e..80b720e3aac1d10ffefedc61394561d4b14c9eb4 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 @@ -11,7 +11,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.maxnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 index 996296c2adc2b5b0e389d5e4ecc2841a6dec6b91..c3b821ea5912468c2c10767bca5e5dddf63e3bd2 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 @@ -6,7 +6,7 @@ !CHECK: omp.yield(%[[MINIMUM_VAL_F]] : f32) !CHECK: combiner !CHECK: ^bb0(%[[ARG0_F:.*]]: f32, %[[ARG1_F:.*]]: f32): -!CHECK: %[[COMB_VAL_F:.*]] = arith.maximumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 +!CHECK: %[[COMB_VAL_F:.*]] = arith.maxnumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 !CHECK: omp.yield(%[[COMB_VAL_F]] : f32) !CHECK: omp.declare_reduction @[[MAX_DECLARE_I:.*]] : i32 init { diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 index 24aa8e46e5bbbd91a62fa54ec2e8a6ba42cd6dd7..b284f8e5d96721345b20349f869f7caa12947e29 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 @@ -11,7 +11,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.minnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 index 268f51c9dc9330c360014dad37a7a42bf2d73fb0..ab33e180ed883dee446720b2175f3a9d40cb1f4e 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 @@ -6,7 +6,7 @@ !CHECK: omp.yield(%[[MAXIMUM_VAL_F]] : f32) !CHECK: combiner !CHECK: ^bb0(%[[ARG0_F:.*]]: f32, %[[ARG1_F:.*]]: f32): -!CHECK: %[[COMB_VAL_F:.*]] = arith.minimumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 +!CHECK: %[[COMB_VAL_F:.*]] = arith.minnumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 !CHECK: omp.yield(%[[COMB_VAL_F]] : f32) !CHECK: omp.declare_reduction @[[MIN_DECLARE_I:.*]] : i32 init { diff --git a/flang/test/Lower/OpenMP/Todo/reduction-allocatable.f90 b/flang/test/Lower/OpenMP/Todo/reduction-allocatable.f90 deleted file mode 100644 index 09aba6920232aa6ae6d8382d82f98099ead622bd..0000000000000000000000000000000000000000 --- a/flang/test/Lower/OpenMP/Todo/reduction-allocatable.f90 +++ /dev/null @@ -1,21 +0,0 @@ -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s - -! CHECK: not yet implemented: Reduction of some types is not supported -subroutine reduction_allocatable - integer, allocatable :: x - integer :: i = 1 - - allocate(x) - x = 0 - - !$omp parallel num_threads(4) - !$omp do reduction(+:x) - do i = 1, 10 - x = x + i - enddo - !$omp end do - !$omp end parallel - - print *, x -end subroutine diff --git a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 new file mode 100644 index 0000000000000000000000000000000000000000..890ae48ce0fc27c5f063e4b1b7e633005f7cd3a3 --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 @@ -0,0 +1,113 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s + +program reduce +integer :: i = 0 +integer, dimension(:), allocatable :: r + +allocate(r(2)) + +!$omp parallel do reduction(+:r) +do i=0,10 + r(1) = i + r(2) = -i +enddo +!$omp end parallel do + +print *,r + +end program + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_heap_Uxi32 : !fir.ref>>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>>): +! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>>> +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.box>> +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[ADDRI:.*]] = fir.convert %[[ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0_I64:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_NULL:.*]] = arith.cmpi eq, %[[ADDRI]], %[[C0_I64]] : i64 +! CHECK: fir.if %[[IS_NULL]] { +! CHECK: %[[NULL_BOX:.*]] = fir.embox %[[ADDR]] : (!fir.heap>) -> !fir.box>> +! CHECK: fir.store %[[NULL_BOX]] to %[[VAL_10]] : !fir.ref>>> +! CHECK: } else { +! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[VAL_6:.*]] = fir.allocmem !fir.array, %[[VAL_4]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[VAL_7:.*]] = arith.constant true +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]]#0 : (!fir.box>) -> !fir.box>> +! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_9]] : i32, !fir.box>> +! CHECK: fir.store %[[VAL_9]] to %[[VAL_10]] : !fir.ref>>> +! CHECK: } +! CHECK: omp.yield(%[[VAL_10]] : !fir.ref>>>) +! CHECK: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>>, %[[VAL_1:.*]]: !fir.ref>>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1 : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_8:.*]] = %[[VAL_7]] to %[[VAL_5]]#1 step %[[VAL_7]] unordered { +! CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box>>, !fir.shapeshift<1>, index) -> !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box>>, !fir.shapeshift<1>, index) -> !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref +! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32 +! CHECK: fir.store %[[VAL_13]] to %[[VAL_9]] : !fir.ref +! CHECK: } +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref>>>) +! CHECK: } cleanup { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>>): +! CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref>>> +! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.heap>) -> i64 +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i64 +! CHECK: %[[VAL_5:.*]] = arith.cmpi ne, %[[VAL_3]], %[[VAL_4]] : i64 +! CHECK: fir.if %[[VAL_5]] { +! CHECK: fir.freemem %[[VAL_2]] : !fir.heap> +! CHECK: } +! CHECK: omp.yield +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref>>> +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = {{.*}}, uniq_name = "_QFEr"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[VAL_4:.*]] = arith.constant 2 : i32 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> index +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_7:.*]] = arith.cmpi sgt, %[[VAL_5]], %[[VAL_6]] : index +! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_5]], %[[VAL_6]] : index +! CHECK: %[[VAL_9:.*]] = fir.allocmem !fir.array, %[[VAL_8]] {fir.must_be_heap = true, uniq_name = "_QFEr.alloc"} +! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_9]](%[[VAL_10]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[VAL_11]] to %[[VAL_3]]#1 : !fir.ref>>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_12:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_14:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_heap_Uxi32 %[[VAL_3]]#0 -> %[[VAL_17:.*]] : !fir.ref>>>) for (%[[VAL_18:.*]]) : i32 = (%[[VAL_14]]) to (%[[VAL_15]]) inclusive step (%[[VAL_16]]) { +! CHECK: fir.store %[[VAL_18]] to %[[VAL_13]]#1 : !fir.ref +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_17]] {fortran_attrs = {{.*}}, uniq_name = "_QFEr"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref>>> +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_21]] (%[[VAL_22]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_20]] to %[[VAL_23]] : i32, !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref +! CHECK: %[[VAL_25:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_26:.*]] = arith.subi %[[VAL_25]], %[[VAL_24]] : i32 +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref>>> +! CHECK: %[[VAL_28:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_29:.*]] = hlfir.designate %[[VAL_27]] (%[[VAL_28]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_29]] : i32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 index 26c9d4f08509647ef2e4065e23ef14f924a5d10a..32f77e66d17ad8ed353d2c035294c2251182d077 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 @@ -17,6 +17,7 @@ end program ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_4:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_1:.*]] = fir.allocmem !fir.array<3xi32> {bindc_name = ".tmp", uniq_name = ""} @@ -25,7 +26,6 @@ end program !fir.shape<1>) -> (!fir.heap>, !fir.heap>) ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> ! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box> -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref>>) ! CHECK: } combiner { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 index bed04401248beddd17393275760769c18c9d8865..28914e78bf388217185de3ec59828d171447d00d 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 @@ -17,6 +17,7 @@ end program ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_4:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_1:.*]] = fir.allocmem !fir.array<3xi32> @@ -25,7 +26,6 @@ end program !fir.shape<1>) -> (!fir.heap>, !fir.heap>) ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> ! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box> -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref>>) ! CHECK: } combiner { diff --git a/flang/test/Lower/OpenMP/parallel-reduction3.f90 b/flang/test/Lower/OpenMP/parallel-reduction3.f90 index ce6bd17265ddba4111ef896397f82ff980e176d7..4d25a4c34bd9a4715f083d9708a505a66f24b7b6 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction3.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction3.f90 @@ -5,6 +5,7 @@ ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1> @@ -12,7 +13,6 @@ ! CHECK: %[[TRUE:.*]] = arith.constant true ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) ! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_7]]#0 : i32, !fir.box> -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_7]]#0 to %[[VAL_8]] : !fir.ref>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref>>) ! CHECK: } combiner { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 new file mode 100644 index 0000000000000000000000000000000000000000..fe3a2505d17c0459ba2b65e64f842d63c09f07fd --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 @@ -0,0 +1,94 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s + +program reduce +integer :: i = 0 +integer, allocatable :: r + +allocate(r) +r = 0 + +!$omp parallel do reduction(+:r) +do i=0,10 + r = i +enddo +!$omp end parallel do + +print *,r + +end program + +! CHECK: omp.declare_reduction @add_reduction_byref_box_heap_i32 : !fir.ref>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): +! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[LOAD:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box> +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>) -> !fir.heap +! CHECK: %[[ADDRI:.*]] = fir.convert %[[ADDR]] : (!fir.heap) -> i64 +! CHECK: %[[C0_I64:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_NULL:.*]] = arith.cmpi eq, %[[ADDRI]], %[[C0_I64]] : i64 +! CHECK: fir.if %[[IS_NULL]] { +! CHECK: %[[NULL_BOX:.*]] = fir.embox %[[ADDR]] : (!fir.heap) -> !fir.box> +! CHECK: fir.store %[[NULL_BOX]] to %[[VAL_2]] : !fir.ref> +! CHECK: } else { +! CHECK: %[[VAL_3:.*]] = fir.allocmem i32 +! CHECK: fir.store %[[VAL_1]] to %[[VAL_3]] : !fir.heap +! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]] : (!fir.heap) -> !fir.box> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref>> +! CHECK: } +! CHECK: omp.yield(%[[VAL_2]] : !fir.ref>>) +! CHECK: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>, %[[VAL_1:.*]]: !fir.ref>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref>> +! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box>) -> !fir.heap +! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box>) -> !fir.heap +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]] : !fir.heap +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]] : !fir.heap +! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_6]], %[[VAL_7]] : i32 +! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.heap +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref>>) +! CHECK: } cleanup { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): +! CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box>) -> !fir.heap +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.heap) -> i64 +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i64 +! CHECK: %[[VAL_5:.*]] = arith.cmpi ne, %[[VAL_3]], %[[VAL_4]] : i64 +! CHECK: fir.if %[[VAL_5]] { +! CHECK: fir.freemem %[[VAL_2]] : !fir.heap +! CHECK: } +! CHECK: omp.yield +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box> {bindc_name = "r", uniq_name = "_QFEr"} +! CHECK: %[[VAL_3:.*]] = fir.zero_bits !fir.heap +! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]] : (!fir.heap) -> !fir.box> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref>> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = {{.*}}, uniq_name = "_QFEr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_6:.*]] = fir.allocmem i32 {fir.must_be_heap = true, uniq_name = "_QFEr.alloc"} +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]] : (!fir.heap) -> !fir.box> +! CHECK: fir.store %[[VAL_7]] to %[[VAL_5]]#1 : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_5]]#0 realloc : i32, !fir.ref>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_9:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_12:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_heap_i32 %[[VAL_5]]#0 -> %[[VAL_14:.*]] : !fir.ref>>) for (%[[VAL_15:.*]]) : i32 = (%[[VAL_11]]) to (%[[VAL_12]]) inclusive step (%[[VAL_13]]) { +! CHECK: fir.store %[[VAL_15]] to %[[VAL_10]]#1 : !fir.ref +! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_14]] {fortran_attrs = {{.*}}, uniq_name = "_QFEr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_16]]#0 : !fir.ref>> +! CHECK: %[[VAL_19:.*]] = fir.box_addr %[[VAL_18]] : (!fir.box>) -> !fir.heap +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_19]] : i32, !fir.heap +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } + diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 index 8f83a30c9fe78224e5a569989400753bcc1dc750..c22407cd35ad01979ac1503548dc9460807151db 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 @@ -26,6 +26,7 @@ end program ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): ! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f64 ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1> @@ -33,7 +34,6 @@ end program ! CHECK: %[[TRUE:.*]] = arith.constant true ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) ! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_7]]#0 : f64, !fir.box> -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_7]]#0 to %[[VAL_8]] : !fir.ref>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref>>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 index a08bca9eb283b5fa21679d130c11ad1c811d89f2..ef122e81d392785b0fa408ac9a5844df304904fe 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 @@ -18,6 +18,7 @@ end program ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_1:.*]] = fir.allocmem !fir.array<2xi32> {bindc_name = ".tmp", uniq_name = ""} @@ -25,7 +26,6 @@ end program ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.heap>, !fir.heap>) ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> ! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box> -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref>>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 index 045208d6f7ffa6adbc219eaf63725d13f68b7d8a..6de8c8eb2e48d7e41c8de152a77ae8324c6114b4 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 @@ -18,6 +18,7 @@ end program ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_1:.*]] = fir.allocmem !fir.array<2xi32> {bindc_name = ".tmp", uniq_name = ""} @@ -25,7 +26,6 @@ end program ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.heap>, !fir.heap>) ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> ! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box> -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref>>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 index ee562bbe15863e0476da7e20bb418516c3a28d9f..2f6921edcb42a5225893915e7663362e94f53f52 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 @@ -13,7 +13,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.maxnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 index 6f11f0ec96a7d3536ebff20ee90401c61d03cb7d..c9cf5cbf4f8c02d367de1b397b37ac8c6df5742b 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 @@ -10,7 +10,7 @@ ! CHECK-LABEL: } combiner { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32, %[[VAL_1:.*]]: f32): -! CHECK: %[[VAL_2:.*]] = arith.maximumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 +! CHECK: %[[VAL_2:.*]] = arith.maxnumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 index c0372117a03b9db5d93dd22bafbeb1323dc10a5c..84a376b46b8fbe607a650d7a0127fb7c6bc2306b 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 @@ -13,7 +13,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.minnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 index 2c694f82e279a42689dcb3cfdd82952cfc9db19a..3ba279acd14c41f8d821ea62520a14a8483e70a7 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 @@ -10,7 +10,7 @@ ! CHECK-LABEL: } combiner { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32, %[[VAL_1:.*]]: f32): -! CHECK: %[[VAL_2:.*]] = arith.minimumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 +! CHECK: %[[VAL_2:.*]] = arith.minnumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } diff --git a/flang/test/Parser/cuf-sanity-common b/flang/test/Parser/cuf-sanity-common index 7f4217fb58355d8242acf10be08a035651a349b6..b097a6aa300458d09a7e0f3cc5f5cc2147dd4835 100644 --- a/flang/test/Parser/cuf-sanity-common +++ b/flang/test/Parser/cuf-sanity-common @@ -32,6 +32,6 @@ module m call globalsub<<<1, 2>>> call globalsub<<<1, 2, 3>>> call globalsub<<<1, 2, 3, 4>>> - allocate(pa(32), stream = 1, pinned = isPinned) + allocate(pa(32), pinned = isPinned) end subroutine end module diff --git a/flang/test/Parser/cuf-sanity-tree.CUF b/flang/test/Parser/cuf-sanity-tree.CUF index dc12759d3ce52fa05dfd538e2fc6f09482538f3d..2820441d5b5f0ae4c032a1bc7f64d5c0dfa82067 100644 --- a/flang/test/Parser/cuf-sanity-tree.CUF +++ b/flang/test/Parser/cuf-sanity-tree.CUF @@ -199,8 +199,6 @@ include "cuf-sanity-common" !CHECK: | | | | | | AllocateShapeSpec !CHECK: | | | | | | | Scalar -> Integer -> Expr = '32_4' !CHECK: | | | | | | | | LiteralConstant -> IntLiteralConstant = '32' -!CHECK: | | | | | AllocOpt -> Stream -> Scalar -> Integer -> Expr = '1_4' -!CHECK: | | | | | | LiteralConstant -> IntLiteralConstant = '1' !CHECK: | | | | | AllocOpt -> Pinned -> Scalar -> Logical -> Variable = 'ispinned' !CHECK: | | | | | | Designator -> DataRef -> Name = 'ispinned' !CHECK: | | | EndSubroutineStmt -> diff --git a/flang/test/Parser/cuf-sanity-unparse.CUF b/flang/test/Parser/cuf-sanity-unparse.CUF index 7ac39448d7bd454d3ae826973e38b7bcb6a39ada..b6921e74fc05ae9ab8b17bb74e569162501f81eb 100644 --- a/flang/test/Parser/cuf-sanity-unparse.CUF +++ b/flang/test/Parser/cuf-sanity-unparse.CUF @@ -37,6 +37,6 @@ include "cuf-sanity-common" !CHECK: CALL globalsub<<<1_4,2_4>>>() !CHECK: CALL globalsub<<<1_4,2_4,3_4>>>() !CHECK: CALL globalsub<<<1_4,2_4,3_4,4_4>>>() -!CHECK: ALLOCATE(pa(32_4), STREAM=1_4, PINNED=ispinned) +!CHECK: ALLOCATE(pa(32_4), PINNED=ispinned) !CHECK: END SUBROUTINE !CHECK: END MODULE diff --git a/flang/test/Semantics/OpenMP/firstprivate02.f90 b/flang/test/Semantics/OpenMP/firstprivate02.f90 new file mode 100644 index 0000000000000000000000000000000000000000..eb2597cb1cc40cae8584eed6de3782c3140b3e05 --- /dev/null +++ b/flang/test/Semantics/OpenMP/firstprivate02.f90 @@ -0,0 +1,20 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! OpenMP Version 5.2, Sections 3.2.1 & 5.3 +subroutine omp_firstprivate(init) + integer :: init + integer :: a(10) + type my_type + integer :: val + end type my_type + type(my_type) :: my_var + + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a FIRSTPRIVATE clause + !$omp parallel firstprivate(a(2)) + a(2) = init + !$omp end parallel + + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a FIRSTPRIVATE clause + !$omp parallel firstprivate(my_var%val) + my_var%val = init + !$omp end parallel +end subroutine diff --git a/flang/test/Semantics/OpenMP/lastprivate03.f90 b/flang/test/Semantics/OpenMP/lastprivate03.f90 new file mode 100644 index 0000000000000000000000000000000000000000..d7fe0c162f27c3a8bc5233c9f4e46648c3c6dcdd --- /dev/null +++ b/flang/test/Semantics/OpenMP/lastprivate03.f90 @@ -0,0 +1,24 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! OpenMP Version 5.2, Sections 3.2.1 & 5.3 +subroutine omp_lastprivate(init) + integer :: init + integer :: i, a(10) + type my_type + integer :: val + end type my_type + type(my_type) :: my_var + + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LASTPRIVATE clause + !$omp do lastprivate(a(2)) + do i=1, 10 + a(2) = init + end do + !$omp end do + + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LASTPRIVATE clause + !$omp do lastprivate(my_var%val) + do i=1, 10 + my_var%val = init + end do + !$omp end do +end subroutine diff --git a/flang/test/Semantics/OpenMP/parallel-private01.f90 b/flang/test/Semantics/OpenMP/parallel-private01.f90 index 0f7ffcabda6bbafea1e38050f6f3126c5413c8df..a3d332c95ed2517185016cdf2859ae6b63f1511f 100644 --- a/flang/test/Semantics/OpenMP/parallel-private01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private01.f90 @@ -10,7 +10,7 @@ program omp_parallel_private type(my_type) :: my_var - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause !$omp parallel private(my_var%array) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-private02.f90 b/flang/test/Semantics/OpenMP/parallel-private02.f90 index b649db972548df0832b810f3c1ae7230788042ff..8cb72159d6ab5cdfaed9dc01d5d244a6ec9eb52f 100644 --- a/flang/test/Semantics/OpenMP/parallel-private02.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private02.f90 @@ -10,7 +10,7 @@ program omp_parallel_private array(i) = i end do - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause !$omp parallel private(array(i)) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-private03.f90 b/flang/test/Semantics/OpenMP/parallel-private03.f90 index 1ec93e3e0dba84904919776db04004858371e998..24a096302e53d8f41991129f312e2b122a0daa46 100644 --- a/flang/test/Semantics/OpenMP/parallel-private03.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private03.f90 @@ -17,7 +17,7 @@ program omp_parallel_private arr(i) = 0.0 end do - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause !$omp parallel private(arr(i),intx) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-private04.f90 b/flang/test/Semantics/OpenMP/parallel-private04.f90 index dbab1564e40fd56849e83284331694fcb3cffa24..67a669c9882a53e61c5dfe6880f9702da00efe20 100644 --- a/flang/test/Semantics/OpenMP/parallel-private04.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private04.f90 @@ -17,7 +17,7 @@ program omp_parallel_private arr(i) = 0.0 end do - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause !$omp parallel private(arr,intx,my_var%array(1)) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-sections01.f90 b/flang/test/Semantics/OpenMP/parallel-sections01.f90 index 2bf58ea2cb295c6ee7c76ea854d125b92135d122..b073cc8223b619efbd42b128b7ae661352f69393 100644 --- a/flang/test/Semantics/OpenMP/parallel-sections01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-sections01.f90 @@ -17,10 +17,10 @@ program OmpConstructSections01 do i = 1, 10 array(i) = i end do -!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause +!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause !$omp parallel sections shared(array(i)) !$omp end parallel sections -!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause +!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause !$omp parallel sections shared(my_var%array) !$omp end parallel sections @@ -30,7 +30,7 @@ program OmpConstructSections01 if (NT) 20, 30, 40 !ERROR: invalid branch into an OpenMP structured block goto 20 -!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause +!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause !$omp parallel sections private(my_var%array) !$omp section print *, "This is a single statement structured block" @@ -53,7 +53,7 @@ program OmpConstructSections01 30 print *, "Error in opening file" !$omp end parallel sections 10 print *, 'Jump from section' -!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause +!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause !$omp parallel sections private(array(i)) !$omp section 40 print *, 'Error in opening file' diff --git a/flang/test/Semantics/OpenMP/parallel-shared01.f90 b/flang/test/Semantics/OpenMP/parallel-shared01.f90 index d9ed9bc2efe2e2853cec309425d1509cf2469ff1..7abfe1f7b16374026e66b35d5703f027de2305a7 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared01.f90 @@ -10,7 +10,7 @@ program omp_parallel_shared type(my_type) :: my_var - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause !$omp parallel shared(my_var%array) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-shared02.f90 b/flang/test/Semantics/OpenMP/parallel-shared02.f90 index f46cfa17ba38fc55c0e7170a99ac163fb7be167f..f59f5236dfd932497650e9cfb0ad2cc4abcba350 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared02.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared02.f90 @@ -10,7 +10,7 @@ program omp_parallel_shared array(i) = i end do - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause !$omp parallel shared(array(i)) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-shared03.f90 b/flang/test/Semantics/OpenMP/parallel-shared03.f90 index 801ffba424a7fd444ed48f1d7e769321ef763c9c..3d9111c7aaf106ea6ae5f46fdc9dd9a74350a244 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared03.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared03.f90 @@ -17,7 +17,7 @@ program omp_parallel_shared arr(i) = 0.0 end do - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause !$omp parallel shared(arr(i),intx) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/parallel-shared04.f90 b/flang/test/Semantics/OpenMP/parallel-shared04.f90 index 6f170c6a6ba7ec555f058536345b13e1bb99593e..06b7fcfa01d7ab1147294e64fd61857045d4c43a 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared04.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared04.f90 @@ -17,7 +17,7 @@ program omp_parallel_shared arr(i) = 0.0 end do - !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE or SHARED clause + !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause !$omp parallel shared(arr,intx,my_var%array(1)) do i = 1, 10 c(i) = a(i) + b(i) + k diff --git a/flang/test/Semantics/OpenMP/resolve03.f90 b/flang/test/Semantics/OpenMP/resolve03.f90 index b9306c4fe9cb4dff532dfcaf1f3e51c2a283b4a5..ebc66ca12ebf445ee4c0d1f005fb3d60b36e84d3 100644 --- a/flang/test/Semantics/OpenMP/resolve03.f90 +++ b/flang/test/Semantics/OpenMP/resolve03.f90 @@ -8,6 +8,9 @@ common /c/ a, b integer a(3), b + common /tc/ x + integer x + !$omp threadprivate(/tc/) A = 1 B = 2 @@ -19,4 +22,26 @@ !$omp end parallel end block print *, a, b + + !$omp parallel + block + !$omp single + x = 18 + !ERROR: COMMON block must be declared in the same scoping unit in which the OpenMP directive or clause appears + !$omp end single copyprivate(/tc/) + end block + !$omp end parallel + + ! Common block names may be used inside nested OpenMP directives. + !$omp parallel + !$omp parallel copyin(/tc/) + x = x + 10 + !$omp end parallel + !$omp end parallel + + !$omp parallel + !$omp single + x = 18 + !$omp end single copyprivate(/tc/) + !$omp end parallel end diff --git a/flang/test/Semantics/cuf02.cuf b/flang/test/Semantics/cuf02.cuf index 881a3005e2817bda7e48eefa2946245a5a378313..a4a229565a3e8c817b1169961150f2fa4230e0b0 100644 --- a/flang/test/Semantics/cuf02.cuf +++ b/flang/test/Semantics/cuf02.cuf @@ -5,14 +5,11 @@ module m end end interface contains - !ERROR: A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL - recursive attributes(device) subroutine s1 + recursive attributes(device) subroutine s1 ! ok end - !ERROR: A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL - pure attributes(device) subroutine s2 + pure attributes(device) subroutine s2 ! ok end - !ERROR: A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL - elemental attributes(device) subroutine s3 + elemental attributes(device) subroutine s3 ! ok end subroutine s4 contains @@ -32,14 +29,11 @@ module m !ERROR: A function may not have ATTRIBUTES(GLOBAL) or ATTRIBUTES(GRID_GLOBAL) attributes(global) real function f1 end - !ERROR: A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL - recursive attributes(global) subroutine s7 + recursive attributes(global) subroutine s7 ! ok end - !ERROR: A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL - pure attributes(global) subroutine s8 + pure attributes(global) subroutine s8 ! ok end - !ERROR: A device subprogram may not be RECURSIVE, PURE, or ELEMENTAL - elemental attributes(global) subroutine s9 + elemental attributes(global) subroutine s9 ! ok end end diff --git a/flang/test/Semantics/cuf03.cuf b/flang/test/Semantics/cuf03.cuf index 8decb8dcaa0f47125b7375abf46f55a29668dd77..472d53db7462aec119dc594f6e5ced42bec08c3b 100644 --- a/flang/test/Semantics/cuf03.cuf +++ b/flang/test/Semantics/cuf03.cuf @@ -32,14 +32,11 @@ module m real, shared, target :: mst !ERROR: Object 'msa' with ATTRIBUTES(SHARED) must be declared in a device subprogram real, shared :: msa(*) - !ERROR: Object 'mm' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument - real, managed :: mm - !ERROR: Object 'mmi' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument - real, managed :: mmi = 1. + real, managed :: mm ! ok + real, managed :: mmi = 1. ! ok real, managed, allocatable :: mml ! ok - !ERROR: Object 'mmp' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument - real, managed, pointer :: mmp ! ok - !ERROR: Object 'mmt' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument + !ERROR: Object 'mmp' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, explicit shape, or a dummy argument + real, managed, pointer :: mmp(:) real, managed, target :: mmt !WARNING: Object 'mp' with ATTRIBUTES(PINNED) should also be allocatable real, pinned :: mp @@ -60,8 +57,7 @@ module m contains attributes(device) subroutine devsubr(n,da) integer, intent(in) :: n - !ERROR: Object 'da' with ATTRIBUTES(DEVICE) may not be assumed size - real, device :: da(*) + real, device :: da(*) ! ok real, managed :: ma(n) ! ok !WARNING: Pointer 'dp' may not be associated in a device subprogram real, device, pointer :: dp diff --git a/flang/test/Semantics/cuf07.cuf b/flang/test/Semantics/cuf07.cuf index b520b5da51264b4e63e746b3b6658cfafa351c6f..c48abb5adf0d41970db447cc0f846a1f986e4661 100644 --- a/flang/test/Semantics/cuf07.cuf +++ b/flang/test/Semantics/cuf07.cuf @@ -23,4 +23,20 @@ module m !BECAUSE: 'ma' is a host-associated allocatable and is not definable in a device subprogram deallocate(ma) end subroutine + + subroutine hostsub() + integer, allocatable, device :: ia(:) + logical :: plog + + !ERROR: Object in ALLOCATE must have PINNED attribute when PINNED option is specified + allocate(ia(100), pinned = plog) + end subroutine + + subroutine host2() + integer, allocatable, pinned :: ia(:) + integer :: istream + + !ERROR: Object in ALLOCATE must have DEVICE attribute when STREAM option is specified + allocate(ia(100), stream = istream) + end subroutine end module diff --git a/flang/test/Semantics/cuf11.cuf b/flang/test/Semantics/cuf11.cuf index de7ff29743242b6cbc4b7c015a152116115a96e0..554ac258e5510189e2cf0bb86227f89c76c5cf69 100644 --- a/flang/test/Semantics/cuf11.cuf +++ b/flang/test/Semantics/cuf11.cuf @@ -30,3 +30,7 @@ logical function compare_h(a,b) !ERROR: 'b' is not an object of derived type; it is implicitly typed compare_h = (a%h .eq. b%h) end + +attributes(global) subroutine sub2() + if (threadIdx%x == 1) print *, "I'm number one" +end subroutine diff --git a/flang/test/Semantics/resolve102.f90 b/flang/test/Semantics/resolve102.f90 index 11f2ce9c8ea561bfeab8457fe12a65d8041e2e46..8f6e2246a57e798366d3675ed8b7a19b78b80d20 100644 --- a/flang/test/Semantics/resolve102.f90 +++ b/flang/test/Semantics/resolve102.f90 @@ -106,3 +106,16 @@ contains g = size(arr) end function end + +module genericInSpec + interface int + procedure ifunc + end interface + contains + function ifunc(x) + integer a(int(kind(1))) ! generic is ok with most compilers + integer(size(a)), intent(in) :: x + ifunc = x + end +end + diff --git a/flang/test/Semantics/select-rank.f90 b/flang/test/Semantics/select-rank.f90 index fa8d2fc4d461dfc7b5b56038dfe783bf57aa84a4..985d744b81d42ef21c347a193f952bd8eabd5c58 100644 --- a/flang/test/Semantics/select-rank.f90 +++ b/flang/test/Semantics/select-rank.f90 @@ -219,11 +219,10 @@ contains SELECT RANK(ptr=>x) RANK (3) PRINT *, "PRINT RANK 3" - !ERROR: 'ptr' is not an object that can appear in an expression + !ERROR: 'kind=' argument must be a constant scalar integer whose value is a supported kind for the intrinsic result type j = INT(0, KIND=MERGE(KIND(0), -1, RANK(ptr) == 0)) RANK (1) PRINT *, "PRINT RANK 1" - !ERROR: 'ptr' is not an object that can appear in an expression j = INT(0, KIND=MERGE(KIND(0), -1, RANK(ptr) == 1)) END SELECT end subroutine diff --git a/flang/test/Semantics/stmt-func02.f90 b/flang/test/Semantics/stmt-func02.f90 index 0f4e8c034f659a1a958622e14eb445b22591e67e..bfed280ded58d10fd536f0bd90b6706c9a29e624 100644 --- a/flang/test/Semantics/stmt-func02.f90 +++ b/flang/test/Semantics/stmt-func02.f90 @@ -1,5 +1,12 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -module m +module m1 + contains + real function rf2(x) + rf2 = x + end +end +module m2 + use m1 real, target :: x = 1. contains function rpf(x) @@ -18,7 +25,11 @@ module m end subroutine test2 !PORTABILITY: Name 'rf' from host scope should have a type declaration before its local statement function definition - rf(x) = 3. + rf(x) = 1. + end + subroutine test2b + !PORTABILITY: Name 'rf2' from host scope should have a type declaration before its local statement function definition + rf2(x) = 1. end subroutine test3 external sf diff --git a/flang/test/Transforms/debug-line-table-inc-file.fir b/flang/test/Transforms/debug-line-table-inc-file.fir index be4f005bf664acd4caff461beb00bf174af791a6..dc75482d4f8a7f077ebbf23c1261b465a2a17323 100644 --- a/flang/test/Transforms/debug-line-table-inc-file.fir +++ b/flang/test/Transforms/debug-line-table-inc-file.fir @@ -1,5 +1,5 @@ -// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s +// RUN: fir-opt --add-debug-info="debug-level=LineTablesOnly" --mlir-print-debuginfo %s | FileCheck %s // REQUIRES: system-linux // Test for included functions that have a different debug location than the current file @@ -30,7 +30,7 @@ module attributes {} { // CHECK: #[[MODULE_LOC]] = loc("{{.*}}simple.f90":0:0) // CHECK: #[[LOC_INC_FILE:.*]] = loc("{{.*}}inc.f90":1:1) // CHECK: #[[LOC_FILE:.*]] = loc("{{.*}}simple.f90":3:1) -// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "Flang", isOptimized = false, emissionKind = LineTablesOnly> +// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly> // CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QPsinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}> // CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QQmain", linkageName = "_QQmain", file = #[[DI_FILE]], {{.*}}> // CHECK: #[[FUSED_LOC_INC_FILE]] = loc(fused<#[[DI_SP_INC]]>[#[[LOC_INC_FILE]]]) diff --git a/flang/test/Transforms/debug-line-table.fir b/flang/test/Transforms/debug-line-table.fir index 0ba88d3d9f7fa2aa93255f3f438dc97e23a84ad3..3b3a39174df0941ee5f20d226f6b752dbb9023bc 100644 --- a/flang/test/Transforms/debug-line-table.fir +++ b/flang/test/Transforms/debug-line-table.fir @@ -1,5 +1,7 @@ -// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s +// RUN: fir-opt --add-debug-info="debug-level=Full" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=FULL +// RUN: fir-opt --add-debug-info="debug-level=LineTablesOnly" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=LINETABLE +// RUN: fir-opt --add-debug-info="is-optimized=true" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=OPT module attributes { fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", llvm.target_triple = "aarch64-unknown-linux-gnu"} { func.func @_QPsb() { @@ -22,7 +24,9 @@ module attributes { fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.dat // CHECK: #[[MODULE_LOC]] = loc("[[DIR_NAME]]/[[FILE_NAME]]":1:1) // CHECK: #[[SB_LOC]] = loc("./simple.f90":2:1) // CHECK: #[[DECL_LOC:.*]] = loc("./simple.f90":10:1) -// CHECK: #di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "Flang", isOptimized = false, emissionKind = LineTablesOnly> +// FULL: #di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang{{.*}}", isOptimized = false, emissionKind = Full> +// OPT: #di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang{{.*}}", isOptimized = true, emissionKind = Full> +// LINETABLE: #di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly> // CHECK: #di_subroutine_type = #llvm.di_subroutine_type // CHECK: #[[SB_SUBPROGRAM:.*]] = #llvm.di_subprogram, compileUnit = #di_compile_unit, scope = #di_file, name = "[[SB_NAME]]", linkageName = "[[SB_NAME]]", file = #di_file, line = 1, scopeLine = 1, subprogramFlags = "Definition|Optimized", type = #di_subroutine_type> // CHECK: #[[DECL_SUBPROGRAM:.*]] = #llvm.di_subprogram diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index dda3b6887be89a86271b4c83f90cb06d3af21ea9..64815a1f5da6224714a3f76064258cd836c4cf83 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -93,17 +93,6 @@ endif() add_custom_target(module_files ALL DEPENDS ${MODULE_FILES}) -# This flang shell script will only work in a POSIX shell. -if (NOT WIN32) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/flang-to-external-fc.in - ${CMAKE_BINARY_DIR}/bin/flang-to-external-fc - @ONLY - ) - add_custom_target(flang-to-external-fc ALL DEPENDS ${CMAKE_BINARY_DIR}/bin/flang-to-external-fc) - install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/flang-to-external-fc DESTINATION "${CMAKE_INSTALL_BINDIR}") -endif() - # TODO Move this to a more suitable location # Copy the generated omp_lib.h header file, if OpenMP support has been configured. if (LLVM_TOOL_OPENMP_BUILD) diff --git a/flang/tools/f18/flang-to-external-fc.in b/flang/tools/f18/flang-to-external-fc.in deleted file mode 100755 index bd16c030121cbb904fcda71d0f5abd0265315f11..0000000000000000000000000000000000000000 --- a/flang/tools/f18/flang-to-external-fc.in +++ /dev/null @@ -1,497 +0,0 @@ -#! /usr/bin/env bash -#===-- tools/f18/flang-to-external-fc.sh --------------------------*- sh -*-===# -# -# 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 -# -#===------------------------------------------------------------------------===# -# A wrapper script for Flang's compiler driver that was developed for testing and -# experimenting. You should be able to use it as a regular compiler driver. It -# will: -# * run Flang's compiler driver to unparse the input source files -# * use the external compiler (defined via FLANG_FC environment variable) to -# compile the unparsed source files -# -# Tested with Bash 4.4. This script will exit immediately if you use an -# older version of Bash. -#===------------------------------------------------------------------------===# -set -euo pipefail - -# Global variables to make the parsing of input arguments a bit easier -INPUT_FILES=() -OPTIONS=() -OUTPUT_FILE="" -MODULE_DIR="" -INTRINSICS_MOD_DIR="" -COMPILE_ONLY="False" -PREPROCESS_ONLY="False" -PRINT_VERSION="False" - -# === check_bash_version ====================================================== -# -# Checks the Bash version that's used to run this script. Exits immediately -# with a non-zero return code if it's lower than 4.4. Otherwise returns 0 -# (success). -# ============================================================================= -check_bash_version() { - message="Error: Your Bash is too old. Please use Bash >= 4.4" - # Major version - [[ "${BASH_VERSINFO[0]:-0}" -lt 4 ]] && echo $message && exit 1 - - # Minor version - if [[ "${BASH_VERSINFO[0]}" == 4 ]]; then - [[ "${BASH_VERSINFO[1]:-0}" -lt 4 ]] && echo $message && exit 1 - fi - - return 0 -} - -# === parse_args ============================================================== -# -# Parse the input arguments passed to this script. Sets the global variables -# declared at the top. -# -# INPUTS: -# $1 - all input arguments -# OUTPUTS: -# Saved in the global variables for this script -# ============================================================================= -parse_args() -{ - while [ "${1:-}" != "" ]; do - # CASE 1: Compiler option - if [[ "${1:0:1}" == "-" ]] ; then - # Output file - extract it into a global variable - if [[ "$1" == "-o" ]] ; then - shift - OUTPUT_FILE="$1" - shift - continue - fi - - # Module directory - extract it into a global variable - if [[ "$1" == "-module-dir" ]]; then - shift - MODULE_DIR="$1" - shift - continue - fi - - # Intrinsics module dir - extract it into a global var - if [[ "$1" == "-intrinsics-module-directory" ]]; then shift - INTRINSICS_MOD_DIR=$1 - shift - continue - fi - - # Module suffix cannot be modified - this script defines it before - # calling the driver. - if [[ "$1" == "-module-suffix" ]]; then - echo "ERROR: \'-module-suffix\' is not available when using the \'flang\' script" - exit 1 - fi - - # Special treatment for `J ` and `-I `. We translate these - # into `J` and `-I` respectively. - if [[ "$1" == "-J" ]] || [[ "$1" == "-I" ]]; then - opt=$1 - shift - OPTIONS+=("$opt$1") - shift - continue - fi - - # This is a regular option - just add it to the list. - OPTIONS+=($1) - if [[ $1 == "-c" ]]; then - COMPILE_ONLY="True" - fi - - if [[ $1 == "-S" ]]; then - COMPILE_ONLY="True" - fi - - if [[ $1 == "-E" ]]; then - PREPROCESS_ONLY="True" - fi - - if [[ $1 == "-v" || $1 == "--version" ]]; then - PRINT_VERSION="True" - fi - - shift - continue - - # CASE 2: A regular file (either source or a library file) - elif [[ -f "$1" ]]; then - INPUT_FILES+=($1) - shift - continue - - else - # CASE 3: Unsupported - echo "ERROR: unrecognised option format: \`$1\`. Perhaps non-existent file?" - exit 1 - fi - done -} - -# === categorise_files ======================================================== -# -# Categorises input files into: -# * Fortran source files (to be compiled) -# * library files (to be linked into the final executable) -# -# INPUTS: -# $1 - all input files to be categorised (array, name reference) -# OUTPUTS: -# $2 - Fortran source files extracted from $1 (array, name reference) -# $3 - other source files extracted from $1 (array, name reference) -# $4 - object files extracted from $1 (array, name reference) -# $5 - lib files extracted from $1 (array, name reference) -# ============================================================================= -categorise_files() -{ - local -n -r all_files=$1 - local -n fortran_sources=$2 - local -n other_sources=$3 - local -n objects=$4 - local -n libs=$5 - - for current_file in "${all_files[@]}"; do - file_ext=${current_file##*.} - if [[ $file_ext == "f" ]] || [[ $file_ext == "f90" ]] || - [[ $file_ext == "f" ]] || [[ $file_ext == "F" ]] || [[ $file_ext == "ff" ]] || - [[ $file_ext == "f90" ]] || [[ $file_ext == "F90" ]] || [[ $file_ext == "ff90" ]] || - [[ $file_ext == "f95" ]] || [[ $file_ext == "F95" ]] || [[ $file_ext == "ff95" ]] || - [[ $file_ext == "cuf" ]] || [[ $file_ext == "CUF" ]] || [[ $file_ext == "f18" ]] || - [[ $file_ext == "F18" ]] || [[ $file_ext == "ff18" ]]; then - fortran_sources+=($current_file) - elif [[ $file_ext == "a" ]] || [[ $file_ext == "so" ]]; then - libs+=($current_file) - elif [[ $file_ext == "o" ]]; then - objects+=($current_file) - else - other_sources+=($current_file) - fi - done -} - -# === categorise_opts ========================================================== -# -# Categorises compiler options into options for: -# * the Flang driver (either new or the "throwaway" driver) -# * the external Fortran driver that will generate the code -# Most options accepted by Flang will be claimed by it. The only exceptions are -# `-I` and `-J`. -# -# INPUTS: -# $1 - all compiler options (array, name reference) -# OUTPUTS: -# $2 - compiler options for the Flang driver (array, name reference) -# $3 - compiler options for the external driver (array, name reference) -# ============================================================================= -categorise_opts() -{ - local -n all_opts=$1 - local -n flang_opts=$2 - local -n fc_opts=$3 - - for opt in "${all_opts[@]}"; do - # These options are claimed by Flang, but should've been dealt with in parse_args. - if [[ $opt == "-module-dir" ]] || - [[ $opt == "-o" ]] || - [[ $opt == "-fintrinsic-modules-path" ]] ; then - echo "ERROR: $opt should've been fully processed by \`parse_args\`" - exit 1 - fi - - if - # The options claimed by Flang. This list needs to be compatible with - # what's supported by Flang's compiler driver (i.e. `flang-new`). - [[ $opt == "-cpp" ]] || - [[ $opt =~ ^-D.* ]] || - [[ $opt == "-E" ]] || - [[ $opt == "-falternative-parameter-statement" ]] || - [[ $opt == "-fbackslash" ]] || - [[ $opt == "-fcolor-diagnostics" ]] || - [[ $opt == "-fdefault-double-8" ]] || - [[ $opt == "-fdefault-integer-8" ]] || - [[ $opt == "-fdefault-real-8" ]] || - [[ $opt == "-ffixed-form" ]] || - [[ $opt =~ ^-ffixed-line-length=.* ]] || - [[ $opt == "-ffree-form" ]] || - [[ $opt == "-fimplicit-none" ]] || - [[ $opt =~ ^-finput-charset=.* ]] || - [[ $opt == "-flarge-sizes" ]] || - [[ $opt == "-flogical-abbreviations" ]] || - [[ $opt == "-fno-color-diagnostics" ]] || - [[ $opt == "-fxor-operator" ]] || - [[ $opt == "-help" ]] || - [[ $opt == "-nocpp" ]] || - [[ $opt == "-pedantic" ]] || - [[ $opt =~ ^-std=.* ]] || - [[ $opt =~ ^-U.* ]] || - [[ $opt == "-Werror" ]]; then - flang_opts+=($opt) - elif - # We translate the following into equivalents understood by `flang-new` - [[ $opt == "-Mfixed" ]] || [[ $opt == "-Mfree" ]]; then - case $opt in - -Mfixed) - flang_opts+=("-ffixed-form") - ;; - - -Mfree) - flang_opts+=("-ffree-form") - ;; - - *) - echo "ERROR: $opt has no equivalent in 'flang-new'" - exit 1 - ;; - esac - elif - # Options that are needed for both Flang and the external driver. - [[ $opt =~ -I.* ]] || - [[ $opt =~ -J.* ]] || - [[ $opt == "-fopenmp" ]] || - [[ $opt == "-fopenacc" ]]; then - flang_opts+=($opt) - fc_opts+=($opt) - else - # All other options are claimed for the external driver. - fc_opts+=($opt) - fi - done -} - -# === get_external_fc_name ==================================================== -# -# Returns the name of external Fortran compiler based on values of -# environment variables. -# ============================================================================= -get_external_fc_name() { - if [[ -v FLANG_FC ]]; then - echo ${FLANG_FC} - elif [[ -v F18_FC ]]; then - # We support F18_FC for backwards compatibility. - echo ${F18_FC} - else - echo gfortran - fi -} - -# === preprocess ============================================================== -# -# Runs the preprocessing. Fortran files are preprocessed using Flang. Other -# files are preprocessed using the external Fortran compiler. -# -# INPUTS: -# $1 - Fortran source files (array, name reference) -# $2 - other source files (array, name reference) -# $3 - compiler flags (array, name reference) -# ============================================================================= -preprocess() { - local -n fortran_srcs=$1 - local -n other_srcs=$2 - local -n opts=$3 - - local ext_fc="$(get_external_fc_name)" - - local -r wd=$(cd "$(dirname "$0")/.." && pwd) - - # Use the provided output file name. - if [[ ! -z ${OUTPUT_FILE:+x} ]]; then - output_definition="-o $OUTPUT_FILE" - fi - - # Preprocess fortran sources using Flang - for idx in "${!fortran_srcs[@]}"; do - if ! "$wd/bin/flang-new" -E "${opts[@]}" "${fortran_srcs[$idx]}" ${output_definition:+$output_definition} - then status=$? - echo flang: in "$PWD", flang-new failed with exit status $status: "$wd/bin/flang-new" "${opts[@]}" "$@" >&2 - exit $status - fi - done - - # Preprocess other sources using Flang - for idx in "${!other_srcs[@]}"; do - if ! $ext_fc -E "${opts[@]}" "${other_srcs[$idx]}" ${output_definition:+$output_definition} - then status=$? - echo flang: in "$PWD", flang-new failed with exit status $status: "$wd/bin/flang-new" "${opts[@]}" "$@" >&2 - exit $status - fi - done -} - -# === get_relocatable_name ====================================================== -# This method generates the name of the output file for the compilation phase -# (triggered with `-c`). If the user of this script is only interested in -# compilation (`flang -c`), use $OUTPUT_FILE provided that it was defined. -# Otherwise, use the usual heuristics: -# * file.f --> file.o -# * file.c --> file.o -# -# INPUTS: -# $1 - input source file for which to generate the output name -# ============================================================================= -get_relocatable_name() { - local -r src_file=$1 - - if [[ $COMPILE_ONLY == "True" ]] && [[ ! -z ${OUTPUT_FILE:+x} ]]; then - out_file="$OUTPUT_FILE" - else - current_ext=${src_file##*.} - new_ext="o" - - out_file=$(basename "${src_file}" "$current_ext")${new_ext} - fi - - echo "$out_file" -} - -# === main ==================================================================== -# Main entry point for this script -# ============================================================================= -main() { - check_bash_version - parse_args "$@" - - if [[ $PRINT_VERSION == "True" ]]; then - echo "flang version @FLANG_VERSION@" - exit 0 - fi - - # Source, object and library files provided by the user - local fortran_source_files=() - local other_source_files=() - local object_files=() - local lib_files=() - categorise_files INPUT_FILES fortran_source_files other_source_files object_files lib_files - - if [[ $PREPROCESS_ONLY == "True" ]]; then - preprocess fortran_source_files other_source_files OPTIONS - exit 0 - fi - - # Options for the Flang driver. - # NOTE: We need `-fc1` to make sure that the frontend driver rather than - # compiler driver is used. We also need to make sure that that's the first - # flag that the driver will see (otherwise it assumes compiler/toolchain - # driver mode). - local flang_options=("-fc1") - # Options for the external Fortran Compiler - local ext_fc_options=() - categorise_opts OPTIONS flang_options ext_fc_options - - local -r wd=$(cd "$(dirname "$0")/.." && pwd) - - # uuidgen is common but not installed by default on some distros - if ! command -v uuidgen &> /dev/null - then - echo "uuidgen is required for generating unparsed file names." - exit 1 - fi - - # STEP 1: Unparse - # Base-name for the unparsed files. These are just temporary files that are - # first generated and then deleted by this script. - # NOTE: We need to make sure that the base-name is unique to every - # invocation. Otherwise we can't use this script in parallel. - local -r unique_id=$(uuidgen | cut -b25-36) - local -r unparsed_file_base="flang_unparsed_file_$unique_id" - - flang_options+=("-module-suffix") - flang_options+=(".f18.mod") - flang_options+=("-fdebug-unparse") - flang_options+=("-fno-analyzed-objects-for-unparse") - - [[ ! -z ${MODULE_DIR} ]] && flang_options+=("-module-dir ${MODULE_DIR}") - [[ ! -z ${INTRINSICS_MOD_DIR} ]] && flang_options+=("-intrinsics-module-directory ${INTRINSICS_MOD_DIR}") - for idx in "${!fortran_source_files[@]}"; do - set +e - "$wd/bin/flang-new" "${flang_options[@]}" "${fortran_source_files[$idx]}" -o "${unparsed_file_base}_${idx}.f90" - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", flang-new failed with exit status "$ret_status": "$wd/bin/flang-new" "${flang_options[@]}" "$@" >&2 - exit "$ret_status" - fi - done - - # STEP 2: Compile Fortran Source Files - local ext_fc="$(get_external_fc_name)" - # Temporary object files generated by this script. To be deleted at the end. - local temp_object_files=() - for idx in "${!fortran_source_files[@]}"; do - # We always have to specify the output name with `-o `. This - # is because we are using the unparsed rather than the original source file - # below. As a result, we cannot rely on the compiler-generated output name. - out_obj_file=$(get_relocatable_name "${fortran_source_files[$idx]}") - - set +e - $ext_fc "-c" "${ext_fc_options[@]}" "${unparsed_file_base}_${idx}.f90" "-o" "${out_obj_file}" - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit "$ret_status" - fi - temp_object_files+=(${out_obj_file}) - done - - # Delete the unparsed files - for idx in "${!fortran_source_files[@]}"; do - rm "${unparsed_file_base}_${idx}.f90" - done - - # STEP 3: Compile Other Source Files - for idx in "${!other_source_files[@]}"; do - # We always specify the output name with `-o `. The user - # might have used `-o`, but we never add it to $OPTIONS (or - # $ext_fc_options). Hence we need to use `get_relocatable_name`. - out_obj_file=$(get_relocatable_name "${other_source_files[$idx]}") - - set +e - $ext_fc "-c" "${ext_fc_options[@]}" "${other_source_files[${idx}]}" "-o" "${out_obj_file}" - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit "$ret_status" - fi - temp_object_files+=(${out_obj_file}) - done - - # STEP 4: Link - if [[ $COMPILE_ONLY == "True" ]]; then - exit 0; - fi - - if [[ ${#temp_object_files[@]} -ge 1 ]] || [[ ${#object_files[@]} -ge 1 ]] ; then - # If $OUTPUT_FILE was specified, use it for the output name. - if [[ ! -z ${OUTPUT_FILE:+x} ]]; then - output_definition="-o $OUTPUT_FILE" - else - output_definition="" - fi - - set +e - $ext_fc "${ext_fc_options[@]}" "${object_files[@]}" "${temp_object_files[@]}" "${lib_files[@]}" ${output_definition:+$output_definition} - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit "$ret_status" - fi - fi - - # Delete intermediate object files - for idx in "${!fortran_source_files[@]}"; do - rm "${temp_object_files[$idx]}" - done -} - -main "${@}" diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index 5fb92a9c299cc3537acd92e953fdcc31e5a968f7..7843513c4d27bb5ba24a4c1081075d4ba56da4e5 100644 --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -176,11 +176,12 @@ def PThreadAPI : PublicAPI<"pthread.h"> { "__pthread_tss_dtor_t", "pthread_attr_t", "pthread_condattr_t", + "pthread_key_t", "pthread_mutex_t", "pthread_mutexattr_t", - "pthread_t", - "pthread_key_t", "pthread_once_t", + "pthread_rwlockattr_t", + "pthread_t", ]; } @@ -259,6 +260,7 @@ def SysTypesAPI : PublicAPI<"sys/types.h"> { "pthread_mutex_t", "pthread_mutexattr_t", "pthread_once_t", + "pthread_rwlockattr_t", "pthread_t", "size_t", "ssize_t", diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 2d8136536b218b145e7cf5325e9ec61c983044b2..a8e289927667121045a32150cf53b9faa8702cfc 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -669,6 +669,10 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.pthread.pthread_mutexattr_setrobust libc.src.pthread.pthread_mutexattr_settype libc.src.pthread.pthread_once + libc.src.pthread.pthread_rwlockattr_destroy + libc.src.pthread.pthread_rwlockattr_getpshared + libc.src.pthread.pthread_rwlockattr_init + libc.src.pthread.pthread_rwlockattr_setpshared libc.src.pthread.pthread_setspecific # sched.h entrypoints diff --git a/libc/docs/dev/code_style.rst b/libc/docs/dev/code_style.rst index ee4e4257c9fa8880068119ca293a363b93df6c2e..170ef6598a9d8e4661317c240df78d679c608079 100644 --- a/libc/docs/dev/code_style.rst +++ b/libc/docs/dev/code_style.rst @@ -219,3 +219,44 @@ defines. Code under ``libc/src/`` should ``#include`` a proxy header from ``hdr/``, which contains a guard on ``LLVM_LIBC_FULL_BUILD`` to either include our header from ``libc/include/`` (fullbuild) or the corresponding underlying system header (overlay). + +Policy on Assembly sources +========================== + +Coding in high level languages such as C++ provides benefits relative to low +level languages like Assembly, such as: + +* Improved safety +* Compile time diagnostics +* Instrumentation + + * Code coverage + * Profile collection +* Sanitization +* Automatic generation of debug info + +While it's not impossible to have Assembly code that correctly provides all of +the above, we do not wish to maintain such Assembly sources in llvm-libc. + +That said, there are a few functions provided by llvm-libc that are impossible +to reliably implement in C++ for all compilers supported for building +llvm-libc. + +We do use inline or out-of-line Assembly in an intentionally minimal set of +places; typically places where the stack or individual register state must be +manipulated very carefully for correctness, or instances where a specific +instruction sequence does not have a corresponding compiler builtin function +today. + +Contributions adding functions implemented purely in Assembly for performance +are not welcome. + +Contributors should strive to stick with C++ for as long as it remains +reasonable to do so. Ideally, bugs should be filed against compiler vendors, +and links to those bug reports should appear in commit messages or comments +that seek to add Assembly to llvm-libc. + +Patches containing any amount of Assembly ideally should be approved by 2 +maintainers. llvm-libc maintainers reserve the right to reject Assembly +contributions that they feel could be better maintained if rewritten in C++, +and to revisit this policy in the future. diff --git a/libc/docs/index.rst b/libc/docs/index.rst index f71920b058d83f297cafe71e37e5aed6f9f4e5b5..5b96987e0aada080d8051fc42a4dbff998d3536e 100644 --- a/libc/docs/index.rst +++ b/libc/docs/index.rst @@ -72,6 +72,7 @@ stages there is no ABI stability in any form. ctype signal threads + setjmp .. toctree:: :hidden: diff --git a/libc/docs/setjmp.rst b/libc/docs/setjmp.rst new file mode 100644 index 0000000000000000000000000000000000000000..d9188dfe1d5e4799836203118d9a3b890ebcdb11 --- /dev/null +++ b/libc/docs/setjmp.rst @@ -0,0 +1,16 @@ +.. include:: check.rst + +setjmp.h Functions +================== + +.. list-table:: + :widths: auto + :align: center + :header-rows: 1 + + * - Function + - Implemented + - Standard + * - longjmp + - |check| + - 7.13.2.1 diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index f5ba2791af3fb8fb4b0fdb4e6e339f33bf89c911..aeef46aabfce5cfb8ee715911461ddb2a1e86ebf 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -322,11 +322,12 @@ add_gen_header( .llvm-libc-types.__pthread_tss_dtor_t .llvm-libc-types.pthread_attr_t .llvm-libc-types.pthread_condattr_t + .llvm-libc-types.pthread_key_t .llvm-libc-types.pthread_mutex_t .llvm-libc-types.pthread_mutexattr_t - .llvm-libc-types.pthread_t - .llvm-libc-types.pthread_key_t .llvm-libc-types.pthread_once_t + .llvm-libc-types.pthread_rwlockattr_t + .llvm-libc-types.pthread_t ) add_gen_header( diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index f26fc0729dc94cbca0c3c70cacd370a3e90878a5..310374fb62ffe05748c9fd2f29efda5d478ecca8 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -54,6 +54,7 @@ add_header(pthread_key_t HDR pthread_key_t.h) add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type) add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h) add_header(pthread_once_t HDR pthread_once_t.h DEPENDS .__futex_word) +add_header(pthread_rwlockattr_t HDR pthread_rwlockattr_t.h) add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type) add_header(rlim_t HDR rlim_t.h) add_header(time_t HDR time_t.h) diff --git a/libc/include/llvm-libc-types/pthread_rwlockattr_t.h b/libc/include/llvm-libc-types/pthread_rwlockattr_t.h new file mode 100644 index 0000000000000000000000000000000000000000..a63de4f7b438c11d13737768ca492694282001e3 --- /dev/null +++ b/libc/include/llvm-libc-types/pthread_rwlockattr_t.h @@ -0,0 +1,15 @@ +//===-- Definition of pthread_rwlockattr_t type ---------------------------===// +// +// 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_LIBC_TYPES_PTHREAD_RWLOCKATTR_T_H +#define LLVM_LIBC_TYPES_PTHREAD_RWLOCKATTR_T_H + +typedef struct { + int pshared; +} pthread_rwlockattr_t; + +#endif // LLVM_LIBC_TYPES_PTHREAD_RWLOCKATTR_T_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 0c88dbd848a3fb99e03b07d03450621114a66bbd..d428d54e32a331deceb6d9eaa0ee63699e3f3973 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -110,6 +110,10 @@ def POSIX : StandardSpec<"POSIX"> { PtrType PThreadCondAttrTPtr = PtrType; ConstType ConstRestrictedPThreadCondAttrTPtr = ConstType>; + NamedType PThreadRWLockAttrTType = NamedType<"pthread_rwlockattr_t">; + PtrType PThreadRWLockAttrTPtr = PtrType; + ConstType ConstPThreadRWLockAttrTPtr = ConstType; + NamedType PThreadMutexAttrTType = NamedType<"pthread_mutexattr_t">; PtrType PThreadMutexAttrTPtr = PtrType; RestrictedPtrType RestrictedPThreadMutexAttrTPtr = RestrictedPtrType; @@ -993,6 +997,7 @@ def POSIX : StandardSpec<"POSIX"> { PThreadMutexTType, PThreadOnceCallback, PThreadOnceT, + PThreadRWLockAttrTType, PThreadStartT, PThreadTSSDtorT, PThreadTType, @@ -1219,6 +1224,26 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec, ArgSpec] >, + FunctionSpec< + "pthread_rwlockattr_destroy", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "pthread_rwlockattr_getpshared", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "pthread_rwlockattr_init", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "pthread_rwlockattr_setpshared", + RetValSpec, + [ArgSpec, ArgSpec] + >, ] >; @@ -1575,6 +1600,7 @@ def POSIX : StandardSpec<"POSIX"> { PThreadMutexAttrTType, PThreadMutexTType, PThreadOnceT, + PThreadRWLockAttrTType, PThreadTType, PidT, SSizeTType, diff --git a/libc/src/__support/OSUtil/fuchsia/io.h b/libc/src/__support/OSUtil/fuchsia/io.h index 9a5e00beaa316cab8f5a88e57379c8790dd6e9ec..f68d734492fabeac0e9e6e250431f13ad1abe5d0 100644 --- a/libc/src/__support/OSUtil/fuchsia/io.h +++ b/libc/src/__support/OSUtil/fuchsia/io.h @@ -9,18 +9,23 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_IO_H #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_IO_H -#ifndef LIBC_COPT_TEST_USE_FUCHSIA -#error this file should only be used by tests -#endif - #include "src/__support/CPP/string_view.h" +#include #include namespace LIBC_NAMESPACE { LIBC_INLINE void write_to_stderr(cpp::string_view msg) { +#if defined(LIBC_COPT_TEST_USE_ZXTEST) + // This is used in standalone context where there is nothing like POSIX I/O. __sanitizer_log_write(msg.data(), msg.size()); +#elif defined(LIBC_COPT_TEST_USE_GTEST) + // The gtest framework already relies on full standard C++ I/O via fdio. + std::cerr << std::string_view{msg.data(), msg.size()}; +#else +#error this file should only be used by tests +#endif } } // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt index 3d6cf6dde010b1d776e9278a9dc769812b7d7ad5..c57475c9114fa61182453471160d35b0434b2b92 100644 --- a/libc/src/pthread/CMakeLists.txt +++ b/libc/src/pthread/CMakeLists.txt @@ -460,6 +460,47 @@ add_entrypoint_object( libc.src.__support.threads.thread ) +add_entrypoint_object( + pthread_rwlockattr_destroy + SRCS + pthread_rwlockattr_destroy.cpp + HDRS + pthread_rwlockattr_destroy.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_rwlockattr_getpshared + SRCS + pthread_rwlockattr_getpshared.cpp + HDRS + pthread_rwlockattr_getpshared.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_rwlockattr_init + SRCS + pthread_rwlockattr_init.cpp + HDRS + pthread_rwlockattr_init.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_rwlockattr_setpshared + SRCS + pthread_rwlockattr_setpshared.cpp + HDRS + pthread_rwlockattr_setpshared.h + DEPENDS + libc.include.pthread + libc.include.errno +) + add_entrypoint_object( pthread_once SRCS diff --git a/libc/src/pthread/pthread_rwlockattr_destroy.cpp b/libc/src/pthread/pthread_rwlockattr_destroy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3ca75112f0ef474cebc103f89dd9870cdb8cd54 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_destroy.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of the pthread_rwlockattr_destroy ------------------===// +// +// 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 "pthread_rwlockattr_destroy.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_destroy, + (pthread_rwlockattr_t * attr [[gnu::unused]])) { + // Initializing a pthread_rwlockattr_t acquires no resources, so this is a + // no-op. + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_destroy.h b/libc/src/pthread/pthread_rwlockattr_destroy.h new file mode 100644 index 0000000000000000000000000000000000000000..5904d6b0041873db7b1d5796d7c90811a73b291b --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_destroy.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_destroy ----*- 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_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_DESTROY_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_DESTROY_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_DESTROY_H diff --git a/libc/src/pthread/pthread_rwlockattr_getpshared.cpp b/libc/src/pthread/pthread_rwlockattr_getpshared.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0dad230a2bde26308c3c24379a9f17d710b43795 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_getpshared.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of the pthread_rwlockattr_getpshared ---------------===// +// +// 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 "pthread_rwlockattr_getpshared.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_getpshared, + (const pthread_rwlockattr_t *attr, int *pshared)) { + *pshared = attr->pshared; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_getpshared.h b/libc/src/pthread/pthread_rwlockattr_getpshared.h new file mode 100644 index 0000000000000000000000000000000000000000..64843e59aae6973767e79ce7578ed4544337aef3 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_getpshared.h @@ -0,0 +1,21 @@ +//===-- Implementation header for pthread_rwlockattr_getpshared -*- 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_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETPSHARED_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETPSHARED_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, + int *pshared); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETPSHARED_H diff --git a/libc/src/pthread/pthread_rwlockattr_init.cpp b/libc/src/pthread/pthread_rwlockattr_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7971f1714db48455d61fac0fa322160d6f933100 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_init.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of the pthread_rwlockattr_init ---------------------===// +// +// 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 "pthread_rwlockattr_init.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t, PTHREAD_PROCESS_PRIVATE + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_init, + (pthread_rwlockattr_t * attr)) { + attr->pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_init.h b/libc/src/pthread/pthread_rwlockattr_init.h new file mode 100644 index 0000000000000000000000000000000000000000..30ae499fb65dc50c1e3d1ead2979471ec39f1c01 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_init.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_init ----*- 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_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_INIT_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_INIT_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_init(pthread_rwlockattr_t *attr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_INIT_H diff --git a/libc/src/pthread/pthread_rwlockattr_setpshared.cpp b/libc/src/pthread/pthread_rwlockattr_setpshared.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bcba7c1b493556a5101ac55c863fd496404b8df --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_setpshared.cpp @@ -0,0 +1,27 @@ +//===-- Implementation of the pthread_rwlockattr_setpshared ---------------===// +// +// 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 "pthread_rwlockattr_setpshared.h" + +#include "src/__support/common.h" + +#include // EINVAL +#include // pthread_rwlockattr_t, PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_setpshared, + (pthread_rwlockattr_t * attr, int pshared)) { + if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE) + return EINVAL; + + attr->pshared = pshared; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_setpshared.h b/libc/src/pthread/pthread_rwlockattr_setpshared.h new file mode 100644 index 0000000000000000000000000000000000000000..393c07d1eecbc5ad92fc663faef8d6302a689a44 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_setpshared.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_setpshared -*- 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_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETPSHARED_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETPSHARED_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETPSHARED_H diff --git a/libc/src/stdlib/bsearch.h b/libc/src/stdlib/bsearch.h index 1de7e051ff6c41abb73541e4fe73bbf08e4a3696..3590198ba55704f804651bd0823529b15de1f24b 100644 --- a/libc/src/stdlib/bsearch.h +++ b/libc/src/stdlib/bsearch.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDLIB_BSEARCH_H #define LLVM_LIBC_SRC_STDLIB_BSEARCH_H -#include +#include // size_t namespace LIBC_NAMESPACE { diff --git a/libc/test/UnitTest/FPExceptMatcher.cpp b/libc/test/UnitTest/FPExceptMatcher.cpp index 53ea72ad9ddd8d176e73cc9cba002a20d70e7e75..c1dfc53924662386ba3d61b6a66e10b910132543 100644 --- a/libc/test/UnitTest/FPExceptMatcher.cpp +++ b/libc/test/UnitTest/FPExceptMatcher.cpp @@ -8,12 +8,16 @@ #include "FPExceptMatcher.h" +#include "test/UnitTest/Test.h" + #include "hdr/types/fenv_t.h" #include "src/__support/FPUtil/FEnvImpl.h" #include #include #include +#if LIBC_TEST_HAS_MATCHERS() + namespace LIBC_NAMESPACE { namespace testing { @@ -49,3 +53,5 @@ FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) { } // namespace testing } // namespace LIBC_NAMESPACE + +#endif // LIBC_TEST_HAS_MATCHERS() diff --git a/libc/test/UnitTest/FPExceptMatcher.h b/libc/test/UnitTest/FPExceptMatcher.h index d36e98d22d4b4e7d79220af58fd75628b3e9d0a6..5136e381081ee45cb6cf0a94529aadcd18304942 100644 --- a/libc/test/UnitTest/FPExceptMatcher.h +++ b/libc/test/UnitTest/FPExceptMatcher.h @@ -9,9 +9,10 @@ #ifndef LLVM_LIBC_TEST_UNITTEST_FPEXCEPTMATCHER_H #define LLVM_LIBC_TEST_UNITTEST_FPEXCEPTMATCHER_H -#ifndef LIBC_COPT_TEST_USE_FUCHSIA - #include "test/UnitTest/Test.h" +#include "test/UnitTest/TestLogger.h" + +#if LIBC_TEST_HAS_MATCHERS() namespace LIBC_NAMESPACE { namespace testing { @@ -24,7 +25,7 @@ class FPExceptMatcher : public Matcher { public: class FunctionCaller { public: - virtual ~FunctionCaller(){}; + virtual ~FunctionCaller() {} virtual void call() = 0; }; @@ -57,8 +58,11 @@ public: true, \ LIBC_NAMESPACE::testing::FPExceptMatcher( \ LIBC_NAMESPACE::testing::FPExceptMatcher::getFunctionCaller(func))) -#else + +#else // !LIBC_TEST_HAS_MATCHERS() + #define ASSERT_RAISES_FP_EXCEPT(func) ASSERT_DEATH(func, WITH_SIGNAL(SIGFPE)) -#endif // LIBC_COPT_TEST_USE_FUCHSIA + +#endif // LIBC_TEST_HAS_MATCHERS() #endif // LLVM_LIBC_TEST_UNITTEST_FPEXCEPTMATCHER_H diff --git a/libc/test/UnitTest/GTest.h b/libc/test/UnitTest/GTest.h new file mode 100644 index 0000000000000000000000000000000000000000..d1637d3ba6583bba3d72fe29fc3fc228c4fea5c3 --- /dev/null +++ b/libc/test/UnitTest/GTest.h @@ -0,0 +1,23 @@ +//===-- Header for using the gtest framework -------------------*- 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_LIBC_UTILS_UNITTEST_GTEST_H +#define LLVM_LIBC_UTILS_UNITTEST_GTEST_H + +#include + +namespace LIBC_NAMESPACE::testing { + +using ::testing::Matcher; +using ::testing::Test; + +} // namespace LIBC_NAMESPACE::testing + +#define LIBC_TEST_HAS_MATCHERS() (1) + +#endif // LLVM_LIBC_UTILS_UNITTEST_GTEST_H diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h index a813a59d2d67f38a7fb6e5806f636b1b4024c679..bba3c6d743becea775b4b45f6d93e0ab5a99e6e9 100644 --- a/libc/test/UnitTest/LibcTest.h +++ b/libc/test/UnitTest/LibcTest.h @@ -446,16 +446,6 @@ CString libc_make_test_file_path_func(const char *file_name); #define EXPECT_STRNE(LHS, RHS) LIBC_TEST_STR_(testStrNe, LHS, RHS, ) #define ASSERT_STRNE(LHS, RHS) LIBC_TEST_STR_(testStrNe, LHS, RHS, return) -//////////////////////////////////////////////////////////////////////////////// -// Errno checks. - -#define ASSERT_ERRNO_EQ(VAL) \ - ASSERT_EQ(VAL, static_cast(LIBC_NAMESPACE::libc_errno)) -#define ASSERT_ERRNO_SUCCESS() \ - ASSERT_EQ(0, static_cast(LIBC_NAMESPACE::libc_errno)) -#define ASSERT_ERRNO_FAILURE() \ - ASSERT_NE(0, static_cast(LIBC_NAMESPACE::libc_errno)) - //////////////////////////////////////////////////////////////////////////////// // Subprocess checks. @@ -494,4 +484,6 @@ CString libc_make_test_file_path_func(const char *file_name); #define WITH_SIGNAL(X) X +#define LIBC_TEST_HAS_MATCHERS() (1) + #endif // LLVM_LIBC_TEST_UNITTEST_LIBCTEST_H diff --git a/libc/test/UnitTest/MemoryMatcher.cpp b/libc/test/UnitTest/MemoryMatcher.cpp index d9d89504dbeba7960d5e8d4bbae0fa7e7b502539..c18bc4a8ab5903a8a210d74003ea4815b700247d 100644 --- a/libc/test/UnitTest/MemoryMatcher.cpp +++ b/libc/test/UnitTest/MemoryMatcher.cpp @@ -10,6 +10,8 @@ #include "test/UnitTest/Test.h" +#if LIBC_TEST_HAS_MATCHERS() + using LIBC_NAMESPACE::testing::tlog; namespace LIBC_NAMESPACE { @@ -76,3 +78,5 @@ void MemoryMatcher::explainError() { } // namespace testing } // namespace LIBC_NAMESPACE + +#endif // LIBC_TEST_HAS_MATCHERS() diff --git a/libc/test/UnitTest/MemoryMatcher.h b/libc/test/UnitTest/MemoryMatcher.h index c548bafb7ae4d628d9d6f7c8e67b5b7166dad007..ab77eff153b40616f6ae48218b125fc9f41eae86 100644 --- a/libc/test/UnitTest/MemoryMatcher.h +++ b/libc/test/UnitTest/MemoryMatcher.h @@ -21,7 +21,7 @@ using MemoryView = LIBC_NAMESPACE::cpp::span; } // namespace testing } // namespace LIBC_NAMESPACE -#ifdef LIBC_COPT_TEST_USE_FUCHSIA +#if !LIBC_TEST_HAS_MATCHERS() #define EXPECT_MEM_EQ(expected, actual) \ do { \ @@ -39,7 +39,7 @@ using MemoryView = LIBC_NAMESPACE::cpp::span; ASSERT_BYTES_EQ(e.data(), a.data(), e.size()); \ } while (0) -#else +#else // LIBC_TEST_HAS_MATCHERS() namespace LIBC_NAMESPACE::testing { @@ -64,6 +64,6 @@ public: #define ASSERT_MEM_EQ(expected, actual) \ ASSERT_THAT(actual, LIBC_NAMESPACE::testing::MemoryMatcher(expected)) -#endif +#endif // !LIBC_TEST_HAS_MATCHERS() #endif // LLVM_LIBC_TEST_UNITTEST_MEMORYMATCHER_H diff --git a/libc/test/UnitTest/Test.h b/libc/test/UnitTest/Test.h index f7ce3cfa5cf62201a4d56121065a92a4c12617f1..c7729606000c41fec2d22bde07c26f0d06cfc5ce 100644 --- a/libc/test/UnitTest/Test.h +++ b/libc/test/UnitTest/Test.h @@ -16,12 +16,35 @@ // redefine it as necessary. #define libc_make_test_file_path(file_name) (file_name) -#if defined(LIBC_COPT_TEST_USE_FUCHSIA) -#include "FuchsiaTest.h" -#elif defined(LIBC_COPT_TEST_USE_PIGWEED) -#include "PigweedTest.h" +// The LIBC_COPT_TEST_USE_* macros can select either of two alternate test +// frameworks: +// * gtest, the well-known model for them all +// * zxtest, the gtest workalike subset sometimes used in the Fuchsia build +// The default is to use llvm-libc's own gtest workalike framework. +// +// All the frameworks provide the basic EXPECT_* and ASSERT_* macros that gtest +// does. The wrapper headers below define LIBC_NAMESPACE::testing::Test as the +// base class for test fixture classes. Each also provides a definition of the +// macro LIBC_TEST_HAS_MATCHERS() for use in `#if` conditionals to guard use of +// gmock-style matchers, which zxtest does not support. + +#if defined(LIBC_COPT_TEST_USE_ZXTEST) +#include "ZxTest.h" +// TODO: Migrate Pigweed to setting LIBC_COPT_TEST_USE_GTEST instead. +#elif defined(LIBC_COPT_TEST_USE_GTEST) || defined(LIBC_COPT_TEST_USE_PIGWEED) +#include "GTest.h" #else #include "LibcTest.h" #endif +// These are defined the same way for each framework, in terms of the macros +// they all provide. + +#define ASSERT_ERRNO_EQ(VAL) \ + ASSERT_EQ(VAL, static_cast(LIBC_NAMESPACE::libc_errno)) +#define ASSERT_ERRNO_SUCCESS() \ + ASSERT_EQ(0, static_cast(LIBC_NAMESPACE::libc_errno)) +#define ASSERT_ERRNO_FAILURE() \ + ASSERT_NE(0, static_cast(LIBC_NAMESPACE::libc_errno)) + #endif // LLVM_LIBC_TEST_UNITTEST_TEST_H diff --git a/libc/test/UnitTest/FuchsiaTest.h b/libc/test/UnitTest/ZxTest.h similarity index 77% rename from libc/test/UnitTest/FuchsiaTest.h rename to libc/test/UnitTest/ZxTest.h index e9e8348ee5ddb04a5bb741c28fd81d7ed7f35e55..e6bd1e8b64372f3fb1581ac2db00805a37fd2ca4 100644 --- a/libc/test/UnitTest/FuchsiaTest.h +++ b/libc/test/UnitTest/ZxTest.h @@ -1,13 +1,13 @@ -//===-- Header for setting up the Fuchsia tests -----------------*- C++ -*-===// +//===-- Header for using Fuchsia's zxtest framework ------------*- 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_LIBC_UTILS_UNITTEST_FUCHSIATEST_H -#define LLVM_LIBC_UTILS_UNITTEST_FUCHSIATEST_H +#ifndef LLVM_LIBC_UTILS_UNITTEST_ZXTEST_H +#define LLVM_LIBC_UTILS_UNITTEST_ZXTEST_H #include @@ -29,7 +29,12 @@ #endif namespace LIBC_NAMESPACE::testing { + using Test = ::zxtest::Test; -} -#endif // LLVM_LIBC_UTILS_UNITTEST_FUCHSIATEST_H +} // namespace LIBC_NAMESPACE::testing + +// zxtest does not have gmock-style matchers. +#define LIBC_TEST_HAS_MATCHERS() (0) + +#endif // LLVM_LIBC_UTILS_UNITTEST_ZXTEST_H diff --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt index 51954a5babd2c589747647a9fdfe1996c086f224..ea75e65f57c9eb8a0ecd1b02284ea57b9c6fb180 100644 --- a/libc/test/src/pthread/CMakeLists.txt +++ b/libc/test/src/pthread/CMakeLists.txt @@ -47,13 +47,28 @@ add_libc_unittest( SRCS pthread_condattr_test.cpp DEPENDS - libc.include.errno + libc.include.llvm-libc-macros.generic_error_number_macros + libc.include.llvm-libc-macros.time_macros libc.include.pthread - libc.include.time libc.src.pthread.pthread_condattr_destroy libc.src.pthread.pthread_condattr_getclock libc.src.pthread.pthread_condattr_getpshared libc.src.pthread.pthread_condattr_init libc.src.pthread.pthread_condattr_setclock libc.src.pthread.pthread_condattr_setpshared - ) +) + +add_libc_unittest( + pthread_rwlockattr_test + SUITE + libc_pthread_unittests + SRCS + pthread_rwlockattr_test.cpp + DEPENDS + libc.include.errno + libc.include.pthread + libc.src.pthread.pthread_rwlockattr_destroy + libc.src.pthread.pthread_rwlockattr_getpshared + libc.src.pthread.pthread_rwlockattr_init + libc.src.pthread.pthread_rwlockattr_setpshared +) diff --git a/libc/test/src/pthread/pthread_condattr_test.cpp b/libc/test/src/pthread/pthread_condattr_test.cpp index accb62de92e45ff9a802089a8374d8603bac6106..5fcdbd99cb0e203d8074ddb09b1f4fcf37b12e37 100644 --- a/libc/test/src/pthread/pthread_condattr_test.cpp +++ b/libc/test/src/pthread/pthread_condattr_test.cpp @@ -6,16 +6,23 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL +#include "include/llvm-libc-macros/time-macros.h" // CLOCK_REALTIME, CLOCK_MONOTONIC +#include "src/pthread/pthread_condattr_destroy.h" +#include "src/pthread/pthread_condattr_getclock.h" +#include "src/pthread/pthread_condattr_getpshared.h" +#include "src/pthread/pthread_condattr_init.h" +#include "src/pthread/pthread_condattr_setclock.h" +#include "src/pthread/pthread_condattr_setpshared.h" #include "test/UnitTest/Test.h" -#include -#include -#include +// TODO: https://github.com/llvm/llvm-project/issues/88997 +#include // PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED TEST(LlvmLibcPThreadCondAttrTest, InitAndDestroy) { pthread_condattr_t cond; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } TEST(LlvmLibcPThreadCondAttrTest, GetDefaultValues) { @@ -26,12 +33,12 @@ TEST(LlvmLibcPThreadCondAttrTest, GetDefaultValues) { // Invalid value. int pshared = 42; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getclock(&cond, &clock), 0); ASSERT_EQ(clock, CLOCK_REALTIME); - ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getpshared(&cond, &pshared), 0); ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } TEST(LlvmLibcPThreadCondAttrTest, SetGoodValues) { @@ -42,14 +49,17 @@ TEST(LlvmLibcPThreadCondAttrTest, SetGoodValues) { // Invalid value. int pshared = 42; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_setclock(&cond, CLOCK_MONOTONIC), 0); - ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setclock(&cond, CLOCK_MONOTONIC), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getclock(&cond, &clock), 0); ASSERT_EQ(clock, CLOCK_MONOTONIC); - ASSERT_EQ(pthread_condattr_setpshared(&cond, PTHREAD_PROCESS_SHARED), 0); - ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setpshared(&cond, + PTHREAD_PROCESS_SHARED), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getpshared(&cond, &pshared), 0); ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } TEST(LlvmLibcPThreadCondAttrTest, SetBadValues) { @@ -60,12 +70,13 @@ TEST(LlvmLibcPThreadCondAttrTest, SetBadValues) { // Invalid value. int pshared = 42; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_setclock(&cond, clock), EINVAL); - ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setclock(&cond, clock), EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getclock(&cond, &clock), 0); ASSERT_EQ(clock, CLOCK_REALTIME); - ASSERT_EQ(pthread_condattr_setpshared(&cond, pshared), EINVAL); - ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setpshared(&cond, pshared), + EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getpshared(&cond, &pshared), 0); ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } diff --git a/libc/test/src/pthread/pthread_rwlockattr_test.cpp b/libc/test/src/pthread/pthread_rwlockattr_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e5ae70df7343f1ffc799c3ab66b24a8086cfc5e --- /dev/null +++ b/libc/test/src/pthread/pthread_rwlockattr_test.cpp @@ -0,0 +1,64 @@ +//===-- Unittests for pthread_rwlockattr_t --------------------------------===// +// +// 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 "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL +#include "src/pthread/pthread_rwlockattr_destroy.h" +#include "src/pthread/pthread_rwlockattr_getpshared.h" +#include "src/pthread/pthread_rwlockattr_init.h" +#include "src/pthread/pthread_rwlockattr_setpshared.h" +#include "test/UnitTest/Test.h" + +// TODO: https://github.com/llvm/llvm-project/issues/88997 +#include // PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED + +TEST(LlvmLibcPThreadRWLockAttrTest, InitAndDestroy) { + pthread_rwlockattr_t attr; + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} + +TEST(LlvmLibcPThreadRWLockAttrTest, GetDefaultValues) { + pthread_rwlockattr_t attr; + + // Invalid value. + int pshared = 42; + + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} + +TEST(LlvmLibcPThreadRWLockAttrTest, SetGoodValues) { + pthread_rwlockattr_t attr; + + // Invalid value. + int pshared = 42; + + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( + &attr, PTHREAD_PROCESS_SHARED), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} + +TEST(LlvmLibcPThreadRWLockAttrTest, SetBadValues) { + pthread_rwlockattr_t attr; + + // Invalid value. + int pshared = 42; + + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared(&attr, pshared), + EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} diff --git a/libc/utils/docgen/setjmp.json b/libc/utils/docgen/setjmp.json new file mode 100644 index 0000000000000000000000000000000000000000..38d4af568926a23f1450910c6acd6e54d632392a --- /dev/null +++ b/libc/utils/docgen/setjmp.json @@ -0,0 +1,15 @@ +{ + "macros": { + "__STDC_VERSION_SETJMP_H__": { + "defined": "7.13.2" + }, + "setjmp": { + "defined": "7.13.1.1" + } + }, + "functions": { + "longjmp": { + "defined": "7.13.2.1" + } + } +} diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake index 5e09cde8035c2700be61e9b23b537c64c5028710..bbedc244a72899534a3e08b4592b3c30e5e5bd4d 100644 --- a/libclc/cmake/modules/AddLibclc.cmake +++ b/libclc/cmake/modules/AddLibclc.cmake @@ -39,6 +39,10 @@ function(compile_to_bc) set( TARGET_ARG "-target" ${ARG_TRIPLE} ) endif() + # Ensure the directory we are told to output to exists + get_filename_component( ARG_OUTPUT_DIR ${ARG_OUTPUT} DIRECTORY ) + file( MAKE_DIRECTORY ${ARG_OUTPUT_DIR} ) + add_custom_command( OUTPUT ${ARG_OUTPUT}${TMP_SUFFIX} COMMAND libclc::clang diff --git a/libcxx/.clang-format b/libcxx/.clang-format index c37ab817bca906a8b1076aebd1753e7b2bc10371..871920f15b5bc9ca60895393f679926cdbab99ee 100644 --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -44,7 +44,6 @@ AttributeMacros: [ '_LIBCPP_NO_SANITIZE', '_LIBCPP_NO_UNIQUE_ADDRESS', '_LIBCPP_NOALIAS', - '_LIBCPP_NODISCARD_EXT', '_LIBCPP_NODISCARD', '_LIBCPP_NORETURN', '_LIBCPP_OVERRIDABLE_FUNC_VIS', diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst index 5b027ed1bd0729a238bd91b2b1feb79430fa4c17..352a198f3774d4623566d81475167925f4e4c7e1 100644 --- a/libcxx/docs/Modules.rst +++ b/libcxx/docs/Modules.rst @@ -69,8 +69,6 @@ Some of the current limitations * The path to the compiler may not be a symlink, ``clang-scan-deps`` does not handle that case properly * Libc++ is not tested with modules instead of headers - * Clang supports modules using GNU extensions, but libc++ does not work using - GNU extensions. * Clang: * Including headers after importing the ``std`` module may fail. This is hard to solve and there is a work-around by first including all headers @@ -105,9 +103,17 @@ Users need to be able to build their own BMI files. system vendors, with the goal that building the BMI files is done by the build system. -Currently this requires a local build of libc++ with modules enabled. Since -modules are not part of the installation yet, they are used from the build -directory. First libc++ needs to be build with module support enabled. +Currently there are two ways to build modules + + * Use a local build of modules from the build directory. This requires + Clang 17 or later and CMake 3.26 or later. + + * Use the installed modules. This requires Clang 18.1.2 or later and + a recent build of CMake. The CMake changes will be part of CMake 3.30. This + method requires you or your distribution to enable module installation. + +Using the local build +~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash @@ -136,7 +142,7 @@ This is a small sample program that uses the module ``std``. It consists of a .. code-block:: cmake cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) - project("module" + project("example" LANGUAGES CXX ) @@ -146,7 +152,6 @@ This is a small sample program that uses the module ``std``. It consists of a set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED YES) - # Libc++ doesn't support compiler extensions for modules. set(CMAKE_CXX_EXTENSIONS OFF) # @@ -214,6 +219,64 @@ Building this project is done with the following steps, assuming the files ``error: module file _deps/std-build/CMakeFiles/std.dir/std.pcm cannot be loaded due to a configuration mismatch with the current compilation [-Wmodule-file-config-mismatch]`` + +Using the installed modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +CMake has added experimental support for importing the Standard modules. This +is available in the current nightly builds and will be part of the 3.30 +release. Currently CMake only supports importing the Standard modules in C++23 +and later. Enabling this for C++20 is on the TODO list of the CMake +developers. + +The example uses the same ``main.cpp`` as above. It uses the following +``CMakeLists.txt``: + +.. code-block:: cmake + + # This requires a recent nightly build. + # This will be part of CMake 3.30.0. + cmake_minimum_required(VERSION 3.29.0 FATAL_ERROR) + + # Enables the Standard module support. This needs to be done + # before selecting the languages. + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + set(CMAKE_CXX_MODULE_STD ON) + + project("example" + LANGUAGES CXX + ) + + # + # Set language version used + # + + set(CMAKE_CXX_STANDARD 23) + set(CMAKE_CXX_STANDARD_REQUIRED YES) + # Currently CMake requires extensions enabled when using import std. + # https://gitlab.kitware.com/cmake/cmake/-/issues/25916 + # https://gitlab.kitware.com/cmake/cmake/-/issues/25539 + set(CMAKE_CXX_EXTENSIONS ON) + + add_executable(main) + target_sources(main + PRIVATE + main.cpp + ) + +Building this project is done with the following steps, assuming the files +``main.cpp`` and ``CMakeLists.txt`` are copied in the current directory. + +.. code-block:: bash + + $ mkdir build + $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER= -DCMAKE_CXX_FLAGS=-stdlib=libc++ + $ ninja -C build + $ build/main + +.. warning:: ```` should point point to the real binary and + not to a symlink. + If you have questions about modules feel free to ask them in the ``#libcxx`` channel on `LLVM's Discord server `__. diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 53cc7a77d1af48675d0f07a4bcfdac24ff4eabbc..8724f321a9d1175b8e5d8d14345b50c69f49a1c9 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -49,6 +49,7 @@ Implemented Papers - P2302R4 - ``std::ranges::contains`` - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with`` - P3029R1 - Better ``mdspan``'s CTAD +- P2387R3 - Pipe support for user-defined range adaptors Improvements and New Features ----------------------------- @@ -79,6 +80,10 @@ Deprecations and Removals in language modes prior to C++20. If you are using these features prior to C++20, please update to ``-std=c++20``. In LLVM 20, the C++20 synchronization library will be removed entirely in language modes prior to C++20. +- ``_LIBCPP_DISABLE_NODISCARD_EXT`` has been removed. ``[[nodiscard]]`` applications are now unconditional. + This decision is based on LEWGs discussion on `P3122 ` and `P3162 ` + to not use ``[[nodiscard]]`` in the standard. + - TODO: The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable that was used to enable the safe mode has been deprecated and setting it triggers an error; use the ``LIBCXX_HARDENING_MODE`` CMake variable with the value ``extensive`` instead. Similarly, the ``_LIBCPP_ENABLE_ASSERTIONS`` macro has been deprecated (setting it to ``1`` still enables the extensive mode in diff --git a/libcxx/docs/Status/Cxx23.rst b/libcxx/docs/Status/Cxx23.rst index b19ff4fdc0f79e6eb51abd363465c3719cf94bab..23d30c8128d71e093cfcd316b37083dd68423759 100644 --- a/libcxx/docs/Status/Cxx23.rst +++ b/libcxx/docs/Status/Cxx23.rst @@ -43,7 +43,6 @@ Paper Status .. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented. .. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations. - .. [#note-P2387R3] P2387R3: ``bind_back`` only .. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well. .. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. .. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 065db97a0b0b15074bbf1265fb464e09230b2429..f75dd288304b270bf48850298db548fb2429e8a2 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -45,7 +45,7 @@ "`P1413R3 `__","LWG","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","February 2022","|Complete| [#note-P1413R3]_","" "`P2255R2 `__","LWG","A type trait to detect reference binding to temporary","February 2022","","" "`P2273R3 `__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0" -"`P2387R3 `__","LWG","Pipe support for user-defined range adaptors","February 2022","|Partial| [#note-P2387R3]_","","|ranges|" +"`P2387R3 `__","LWG","Pipe support for user-defined range adaptors","February 2022","|Complete|","19.0","|ranges|" "`P2440R1 `__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|" "`P2441R2 `__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|" "`P2442R1 `__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|" diff --git a/libcxx/docs/Status/RangesMajorFeatures.csv b/libcxx/docs/Status/RangesMajorFeatures.csv index c0bec8d924e8a9bc25a2b81a8914ac7c1d20dfb5..d00fbce9edf4893fbdd02899bfd677c120deebb8 100644 --- a/libcxx/docs/Status/RangesMajorFeatures.csv +++ b/libcxx/docs/Status/RangesMajorFeatures.csv @@ -1,5 +1,5 @@ Standard,Name,Assignee,CL,Status C++23,`ranges::to `_,Konstantin Varlamov,`D142335 `_,Complete -C++23,`Pipe support for user-defined range adaptors `_,Unassigned,No patch yet,Not started +C++23,`Pipe support for user-defined range adaptors `_,"Louis Dionne, Jakub Mazurkiewicz, and Xiaoyang Liu",Various,Complete C++23,`Formatting Ranges `_,Mark de Wever,Various,Complete C++20,`Stashing stashing iterators for proper flattening `_,Jakub Mazurkiewicz,Various,In progress diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index 8f945656de1ca658ada6ed6ed1e8fe8058ec3a9c..e7aaf4e1fbcf9cc23c567cd98d52a249896553e1 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -196,10 +196,6 @@ safety annotations. replacement scenarios from working, e.g. replacing `operator new` and expecting a non-replaced `operator new[]` to call the replaced `operator new`. -**_LIBCPP_DISABLE_NODISCARD_EXT**: - This macro disables library-extensions of ``[[nodiscard]]``. - See :ref:`Extended Applications of [[nodiscard]] ` for more information. - **_LIBCPP_DISABLE_DEPRECATION_WARNINGS**: This macro disables warnings when using deprecated components. For example, using `std::auto_ptr` when compiling in C++11 mode will normally trigger a @@ -279,29 +275,6 @@ Libc++ Extensions This section documents various extensions provided by libc++, how they're provided, and any information regarding how to use them. -.. _nodiscard extension: - -Extended applications of ``[[nodiscard]]`` ------------------------------------------- - -The ``[[nodiscard]]`` attribute is intended to help users find bugs where -function return values are ignored when they shouldn't be. After C++17 the -C++ standard has started to declared such library functions as ``[[nodiscard]]``. -However, this application is limited and applies only to dialects after C++17. -Users who want help diagnosing misuses of STL functions may desire a more -liberal application of ``[[nodiscard]]``. - -For this reason libc++ provides an extension that does just that! The -extension is enabled by default and can be disabled by defining ``_LIBCPP_DISABLE_NODISCARD_EXT``. -The extended applications of ``[[nodiscard]]`` takes two forms: - -1. Backporting ``[[nodiscard]]`` to entities declared as such by the - standard in newer dialects, but not in the present one. - -2. Extended applications of ``[[nodiscard]]``, at the library's discretion, - applied to entities never declared as such by the standard. You can find - all such applications by grepping for ``_LIBCPP_NODISCARD_EXT``. - Extended integral type support ------------------------------ diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 4ecd834c5382ae03335a533296e0e45609674f75..1296c536bc882c81d2b89a65656c5e4447bca140 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -957,7 +957,6 @@ set(files istream iterator latch - libcxx.imp limits list locale @@ -1036,6 +1035,15 @@ foreach(f ${files}) list(APPEND _all_includes "${dst}") endforeach() +# Generate the IWYU mapping. This depends on all header files but it's also considered as an +# "include" for dependency tracking. +add_custom_command(OUTPUT "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_iwyu_mapping.py" "-o" "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + DEPENDS ${_all_includes} + COMMENT "Generate the mapping file for include-what-you-use" +) +list(APPEND _all_includes "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp") + add_custom_target(generate-cxx-headers ALL DEPENDS ${_all_includes}) add_library(cxx-headers INTERFACE) @@ -1068,8 +1076,8 @@ if (LIBCXX_INSTALL_HEADERS) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT cxx-headers) - # Install the generated modulemap file to the generic include dir. - install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" + # Install the generated IWYU file to the generic include dir. + install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT cxx-headers) diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h index 7819e2cf49b9fa951948fe83aeaf150bdfc119e1..6f15456e3a4d074c2cf069b1a2cb46b22e184736 100644 --- a/libcxx/include/__algorithm/adjacent_find.h +++ b/libcxx/include/__algorithm/adjacent_find.h @@ -26,7 +26,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { if (__first == __last) return __first; @@ -40,13 +40,13 @@ __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { return std::__adjacent_find(std::move(__first), std::move(__last), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { return std::adjacent_find(std::move(__first), std::move(__last), __equal_to()); } diff --git a/libcxx/include/__algorithm/all_of.h b/libcxx/include/__algorithm/all_of.h index 237f8495c645f24fb3af37d5cab15d8885118e6f..ec84eea75929668ebbf84f06ff6a04ea8cf64d57 100644 --- a/libcxx/include/__algorithm/all_of.h +++ b/libcxx/include/__algorithm/all_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/any_of.h b/libcxx/include/__algorithm/any_of.h index 8ba7aae2b225e1712af63c8b4f4e53b677df83b5..b5ff778c4171dc81754bd14e0962fbd9b1277763 100644 --- a/libcxx/include/__algorithm/any_of.h +++ b/libcxx/include/__algorithm/any_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/binary_search.h b/libcxx/include/__algorithm/binary_search.h index 7a77d7b5447bda7ce988e7534582d4c9b07919e2..6065fc37274dce1301006e83ac02e3abea1e6eac 100644 --- a/libcxx/include/__algorithm/binary_search.h +++ b/libcxx/include/__algorithm/binary_search.h @@ -22,14 +22,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { __first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp); return __first != __last && !__comp(__value, *__first); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::binary_search(__first, __last, __value, __less<>()); } diff --git a/libcxx/include/__algorithm/clamp.h b/libcxx/include/__algorithm/clamp.h index 003bf70dd4f01db714438aa13a012f7b9b77d32c..1a5a3d0744be9c35d8aa2222a87d0580b4d6b42a 100644 --- a/libcxx/include/__algorithm/clamp.h +++ b/libcxx/include/__algorithm/clamp.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& +[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, _LIBCPP_LIFETIMEBOUND const _Tp& __lo, _LIBCPP_LIFETIMEBOUND const _Tp& __hi, @@ -31,7 +31,7 @@ clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& +[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, _LIBCPP_LIFETIMEBOUND const _Tp& __lo, _LIBCPP_LIFETIMEBOUND const _Tp& __hi) { diff --git a/libcxx/include/__algorithm/count.h b/libcxx/include/__algorithm/count.h index 23a7d3c4dcfed66e2a50eaa523364b416d460e1e..1cfe7f631ac1b79a435d1e1623fc15c02bf3b4fb 100644 --- a/libcxx/include/__algorithm/count.h +++ b/libcxx/include/__algorithm/count.h @@ -79,7 +79,7 @@ __count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __l } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> count(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __identity __proj; return std::__count<_ClassicAlgPolicy>(__first, __last, __value, __proj); diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h index 04f52b894f8bd41e4ffd8cdea64ec97c6b62e5bc..25782069d03275dfac35754fca952dc5ccf2a8c5 100644 --- a/libcxx/include/__algorithm/count_if.h +++ b/libcxx/include/__algorithm/count_if.h @@ -20,9 +20,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - typename iterator_traits<_InputIterator>::difference_type - count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +typename iterator_traits<_InputIterator>::difference_type +count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { typename iterator_traits<_InputIterator>::difference_type __r(0); for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h index 1341d9e4159ba5874d3618a865dbe044ed87c1b7..bfc8f72f6eb1953efb8c01100068f0d976b8eab4 100644 --- a/libcxx/include/__algorithm/equal.h +++ b/libcxx/include/__algorithm/equal.h @@ -55,14 +55,14 @@ __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { return std::__equal_iter_impl( std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::equal(__first1, __last1, __first2, __equal_to()); } @@ -96,7 +96,7 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -119,7 +119,7 @@ equal(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::equal(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h index 2b086abf1794fde469a65ef5bd584db620fc3fd3..09bbf8f006021a350cd4a2cd7216ff26f88aeb75 100644 --- a/libcxx/include/__algorithm/equal_range.h +++ b/libcxx/include/__algorithm/equal_range.h @@ -60,7 +60,7 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); @@ -73,7 +73,7 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::equal_range(std::move(__first), std::move(__last), __value, __less<>()); } diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h index 7d7631b6e98a96d1e3044b8a8fca8e727aa530df..d603568731322285af7d27c45626303644af7516 100644 --- a/libcxx/include/__algorithm/find.h +++ b/libcxx/include/__algorithm/find.h @@ -169,7 +169,7 @@ struct __find_segment { // public API template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __identity __proj; return std::__rewrap_iter( diff --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h index 4c26891666b2238d731fc8525f232ce0109109b6..7e08e7953534eb039476ab16505d1885f7286f5c 100644 --- a/libcxx/include/__algorithm/find_end.h +++ b/libcxx/include/__algorithm/find_end.h @@ -205,7 +205,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Fo } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -215,7 +215,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::find_end(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/find_first_of.h b/libcxx/include/__algorithm/find_first_of.h index 14271cccc42b14254568c86762c8d6d3643c1a17..6b99f562f8804e3780071a1870ee4388af74b9c6 100644 --- a/libcxx/include/__algorithm/find_first_of.h +++ b/libcxx/include/__algorithm/find_first_of.h @@ -35,7 +35,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_fir } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -45,7 +45,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/find_if.h b/libcxx/include/__algorithm/find_if.h index 09a39f646351c37e06d78902379b6a00187fb5bb..22092d352b06e7f97319091c8f8e10cc6e1de5ed 100644 --- a/libcxx/include/__algorithm/find_if.h +++ b/libcxx/include/__algorithm/find_if.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/find_if_not.h b/libcxx/include/__algorithm/find_if_not.h index bf29ebb7cdd93c7cba6a05c3d4f901b05361fff6..cc2001967f0c5a82ab91a4412824c1e0ef5806af 100644 --- a/libcxx/include/__algorithm/find_if_not.h +++ b/libcxx/include/__algorithm/find_if_not.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/fold.h b/libcxx/include/__algorithm/fold.h index 1a9d76b50d83c9618f4247eb27278220a389d43d..255658f52324991bdb4601abc87ab9424e8134f2 100644 --- a/libcxx/include/__algorithm/fold.h +++ b/libcxx/include/__algorithm/fold.h @@ -78,8 +78,7 @@ concept __indirectly_binary_left_foldable = struct __fold_left_with_iter { template _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto - operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { using _Up = decay_t>>; if (__first == __last) { @@ -95,7 +94,7 @@ struct __fold_left_with_iter { } template > _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { auto __result = operator()(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)); using _Up = decay_t>>; @@ -107,13 +106,12 @@ inline constexpr auto fold_left_with_iter = __fold_left_with_iter(); struct __fold_left { template _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto - operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { return fold_left_with_iter(std::move(__first), std::move(__last), std::move(__init), std::ref(__f)).value; } template > _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { return fold_left_with_iter(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)).value; } }; diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h index 05d45365eb806ffcf21cc3ba5807668aac606a45..62af03c3742608eac2d3fda827f2c3d6be952b4c 100644 --- a/libcxx/include/__algorithm/includes.h +++ b/libcxx/include/__algorithm/includes.h @@ -47,7 +47,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __includes( } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -67,7 +67,7 @@ includes(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::includes(std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __less<>()); } diff --git a/libcxx/include/__algorithm/is_heap.h b/libcxx/include/__algorithm/is_heap.h index 0d2d43c2c3abd626edb194ca86a0a413dbe830f6..c589b804a5dc08f3c82fddb6e48be5ef5e7a7ebc 100644 --- a/libcxx/include/__algorithm/is_heap.h +++ b/libcxx/include/__algorithm/is_heap.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { return std::is_heap(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/is_heap_until.h b/libcxx/include/__algorithm/is_heap_until.h index 1eae3b86b90dfbd34521fc0f7c5bb86d1a34c89c..a174f2453cfcc0dc43ae0c3c82d29648fce8cf8f 100644 --- a/libcxx/include/__algorithm/is_heap_until.h +++ b/libcxx/include/__algorithm/is_heap_until.h @@ -46,13 +46,13 @@ __is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) { return std::__is_heap_until(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/is_partitioned.h b/libcxx/include/__algorithm/is_partitioned.h index 71feed33206058aff15294b2955e6a109ba7a093..1f7c8b0b267e75b72b00d6909089e2c127671b11 100644 --- a/libcxx/include/__algorithm/is_partitioned.h +++ b/libcxx/include/__algorithm/is_partitioned.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h index 4226151222bbde9efc007bbef86f870f9bac7d94..2ddfb32a212bbb458c89221a8fe484bb8952cb81 100644 --- a/libcxx/include/__algorithm/is_permutation.h +++ b/libcxx/include/__algorithm/is_permutation.h @@ -113,7 +113,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl( // 2+1 iterators, predicate. Not used by range algorithms. template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( _ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _BinaryPredicate&& __pred) { // Shorten sequences as much as possible by lopping of any equal prefix. for (; __first1 != __last1; ++__first1, (void)++__first2) { @@ -247,7 +247,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( // 2+1 iterators, predicate template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) { static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, "The predicate has to be callable"); @@ -257,7 +257,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool i // 2+1 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { return std::is_permutation(__first1, __last1, __first2, __equal_to()); } @@ -266,7 +266,7 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt // 2+2 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::__is_permutation<_ClassicAlgPolicy>( std::move(__first1), @@ -280,7 +280,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 // 2+2 iterators, predicate template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, diff --git a/libcxx/include/__algorithm/is_sorted.h b/libcxx/include/__algorithm/is_sorted.h index 1874cace882c1edf368166c0099257d3a4b8806b..3befb1ac9c26a691f89aaa6143597e196fcf1882 100644 --- a/libcxx/include/__algorithm/is_sorted.h +++ b/libcxx/include/__algorithm/is_sorted.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last) { return std::is_sorted(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/is_sorted_until.h b/libcxx/include/__algorithm/is_sorted_until.h index 7450440df2d8b8c52b5d244c969bd782818509a6..53a49f00de31e8536a828fc1825c7c94effc2042 100644 --- a/libcxx/include/__algorithm/is_sorted_until.h +++ b/libcxx/include/__algorithm/is_sorted_until.h @@ -35,13 +35,13 @@ __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __ } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { return std::is_sorted_until(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/lexicographical_compare.h b/libcxx/include/__algorithm/lexicographical_compare.h index 3efd8e24bf6c9c3df0711982b962525de70f3e8d..edc29e269c88cab309b97c2ef625948fca301eb5 100644 --- a/libcxx/include/__algorithm/lexicographical_compare.h +++ b/libcxx/include/__algorithm/lexicographical_compare.h @@ -37,7 +37,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __lexicographical_compa } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -47,7 +47,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>()); } diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h index 50ebdc647a97abbe05a9df3bb888325f39e86812..a5872e90cf8d2960655c953fe486bcce16dc8ee2 100644 --- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h +++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h @@ -90,7 +90,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_pa } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp __comp) -> decltype(__comp(*__first1, *__first2)) { static_assert(__comparison_category, @@ -110,7 +110,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compa } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::lexicographical_compare_three_way( std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::compare_three_way()); diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h index 8f57f3592c4b24aa5601d451e7211d8a4ce73015..8fd355a7cfc4a0446edca72860f8f106e1be8d92 100644 --- a/libcxx/include/__algorithm/lower_bound.h +++ b/libcxx/include/__algorithm/lower_bound.h @@ -47,7 +47,7 @@ __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); auto __proj = std::__identity(); @@ -55,7 +55,7 @@ lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::lower_bound(__first, __last, __value, __less<>()); } diff --git a/libcxx/include/__algorithm/max.h b/libcxx/include/__algorithm/max.h index 8171677f155c9ce765932d9af90bbb955da514fa..d4c99f6f364367410f83c8ca32f51d4ddb4cef63 100644 --- a/libcxx/include/__algorithm/max.h +++ b/libcxx/include/__algorithm/max.h @@ -25,13 +25,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__a, __b) ? __b : __a; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::max(__a, __b, __less<>()); } @@ -39,13 +39,13 @@ max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t, _Compare __comp) { return *std::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { return *std::max_element(__t.begin(), __t.end(), __less<>()); } diff --git a/libcxx/include/__algorithm/max_element.h b/libcxx/include/__algorithm/max_element.h index f1d4f1cd0938c11081fb978fe3534ef20be86b48..c036726cbccd8bca3337c0dfffcd69482b4106d3 100644 --- a/libcxx/include/__algorithm/max_element.h +++ b/libcxx/include/__algorithm/max_element.h @@ -35,13 +35,13 @@ __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { return std::max_element(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/min.h b/libcxx/include/__algorithm/min.h index 919508486fd5b39e2d4ea6ae356e4255ce878233..1bafad8a461eb93d1d6a2f2a493fe99019861715 100644 --- a/libcxx/include/__algorithm/min.h +++ b/libcxx/include/__algorithm/min.h @@ -25,13 +25,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? __b : __a; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::min(__a, __b, __less<>()); } @@ -39,13 +39,13 @@ min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t, _Compare __comp) { return *std::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { return *std::min_element(__t.begin(), __t.end(), __less<>()); } diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h index c576d665601db3bf9a198a2fca54ba1cd32e433c..65f3594d630cef822b3552d2a182e1de8aa471df 100644 --- a/libcxx/include/__algorithm/min_element.h +++ b/libcxx/include/__algorithm/min_element.h @@ -48,7 +48,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element(_Iter __ } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); @@ -59,7 +59,7 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last) { return std::min_element(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/minmax.h b/libcxx/include/__algorithm/minmax.h index 5227b885717542384dd36fdd3e6b517014898282..9feda2b4c0da90f16ac6ae86f208595158ae80d3 100644 --- a/libcxx/include/__algorithm/minmax.h +++ b/libcxx/include/__algorithm/minmax.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? pair(__b, __a) : pair(__a, __b); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::minmax(__a, __b, __less<>()); } @@ -38,7 +38,7 @@ minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __ #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) { static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable"); __identity __proj; @@ -47,7 +47,7 @@ minmax(initializer_list<_Tp> __t, _Compare __comp) { } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t) { return std::minmax(__t, __less<>()); } diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h index ff8cda321cef47df7e3d467709d2a01f6aba9afb..43cb23347c3465955984f197da4065a2a03a57a2 100644 --- a/libcxx/include/__algorithm/minmax_element.h +++ b/libcxx/include/__algorithm/minmax_element.h @@ -79,7 +79,7 @@ __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator"); @@ -90,9 +90,8 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - pair<_ForwardIterator, _ForwardIterator> - minmax_element(_ForwardIterator __first, _ForwardIterator __last) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> +minmax_element(_ForwardIterator __first, _ForwardIterator __last) { return std::minmax_element(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h index 4ada29eabc470c93115d00b06766abb546ec537a..c2b3f8938f71113a4b501699018f0465488e1daa 100644 --- a/libcxx/include/__algorithm/mismatch.h +++ b/libcxx/include/__algorithm/mismatch.h @@ -122,7 +122,7 @@ __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __ #endif // _LIBCPP_VECTORIZE_ALGORITHMS template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { __identity __proj; auto __res = std::__mismatch( @@ -131,14 +131,14 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::mismatch(__first1, __last1, __first2, __equal_to()); } #if _LIBCPP_STD_VER >= 14 template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { while (__first1 != __last1 && __first2 != __last2) { if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) @@ -150,14 +150,14 @@ template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { auto __len = std::min(__last1 - __first1, __last2 - __first2); return std::__mismatch(__first1, __first1 + __len, __first2, __pred, __proj1, __proj2); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -176,7 +176,7 @@ mismatch(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::mismatch(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/none_of.h b/libcxx/include/__algorithm/none_of.h index ce59187a3a6504a064e4d72b599a0cf86815b474..50841ba17cc63ed69c914808cc5184158c466d1f 100644 --- a/libcxx/include/__algorithm/none_of.h +++ b/libcxx/include/__algorithm/none_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/pstl_any_all_none_of.h b/libcxx/include/__algorithm/pstl_any_all_none_of.h index 911a7e42b3fa3f711cc9905913b572c387a18778..e27463dab8a3109e7d1fae3e330ee85184961c77 100644 --- a/libcxx/include/__algorithm/pstl_any_all_none_of.h +++ b/libcxx/include/__algorithm/pstl_any_all_none_of.h @@ -58,7 +58,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "any_of requires a ForwardIterator"); auto __res = std::__any_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); @@ -97,7 +97,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "all_of requires a ForwardIterator"); auto __res = std::__all_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); @@ -134,7 +134,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "none_of requires a ForwardIterator"); auto __res = std::__none_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); diff --git a/libcxx/include/__algorithm/pstl_is_partitioned.h b/libcxx/include/__algorithm/pstl_is_partitioned.h index c016b388e3784a6aa660efd7722fe1fa03eb3c71..2dd5cf3ca2a21abc6b66b7a6cf617bd87ab89c9f 100644 --- a/libcxx/include/__algorithm/pstl_is_partitioned.h +++ b/libcxx/include/__algorithm/pstl_is_partitioned.h @@ -61,7 +61,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "is_partitioned requires ForwardIterators"); auto __res = std::__is_partitioned(__policy, std::move(__first), std::move(__last), std::move(__pred)); diff --git a/libcxx/include/__algorithm/ranges_adjacent_find.h b/libcxx/include/__algorithm/ranges_adjacent_find.h index a10b04167ede697868f6f2386e5e0868f1c24b57..3c54f723310a6f8257c4d405d71216c2643da742 100644 --- a/libcxx/include/__algorithm/ranges_adjacent_find.h +++ b/libcxx/include/__algorithm/ranges_adjacent_find.h @@ -53,7 +53,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_binary_predicate, projected<_Iter, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -62,7 +62,7 @@ struct __fn { class _Proj = identity, indirect_binary_predicate, _Proj>, projected, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_all_of.h b/libcxx/include/__algorithm/ranges_all_of.h index 8976541d590cad16740b6a60aedb77e1cc86295b..2f603b32f32d08a29305271e91ac646ebf27ca33 100644 --- a/libcxx/include/__algorithm/ranges_all_of.h +++ b/libcxx/include/__algorithm/ranges_all_of.h @@ -45,7 +45,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -53,7 +53,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_any_of.h b/libcxx/include/__algorithm/ranges_any_of.h index 7c775f5f64dec0983013b5e16993ae0ac979fa64..205fcecc086e7a65766bea679002819ee889bc21 100644 --- a/libcxx/include/__algorithm/ranges_any_of.h +++ b/libcxx/include/__algorithm/ranges_any_of.h @@ -45,7 +45,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -53,7 +53,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_binary_search.h b/libcxx/include/__algorithm/ranges_binary_search.h index f3b7842d5cccd4428b6a99fa9e10ff33b7b75225..1ef2bd62b5995ab9799eb766c2f78bbaaa392ccc 100644 --- a/libcxx/include/__algorithm/ranges_binary_search.h +++ b/libcxx/include/__algorithm/ranges_binary_search.h @@ -39,7 +39,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); @@ -49,7 +49,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index f5ef5fd7f26ec88bf6e3e95fdca3db5fd31b1217..e6181ef9435e098862a0e0e38c48978e30589e85 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -35,7 +35,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( const _Type& __value, const _Type& __low, const _Type& __high, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( !bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), diff --git a/libcxx/include/__algorithm/ranges_contains.h b/libcxx/include/__algorithm/ranges_contains.h index 00d0e54019887c448b6b9321ff0654ed42b867f0..4836c3baed173eea19a017784dc7e8df3f4edb64 100644 --- a/libcxx/include/__algorithm/ranges_contains.h +++ b/libcxx/include/__algorithm/ranges_contains.h @@ -37,14 +37,14 @@ namespace __contains { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) { return ranges::find(std::move(__first), __last, __value, std::ref(__proj)) != __last; } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) { return ranges::find(ranges::begin(__range), ranges::end(__range), __value, std::ref(__proj)) != ranges::end(__range); diff --git a/libcxx/include/__algorithm/ranges_contains_subrange.h b/libcxx/include/__algorithm/ranges_contains_subrange.h index bc5a86ce3d696a164f6396b90eb7bf6a60c78bec..4398c457fd054d3c02b774b7543588fb822f9410 100644 --- a/libcxx/include/__algorithm/ranges_contains_subrange.h +++ b/libcxx/include/__algorithm/ranges_contains_subrange.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -67,7 +67,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { if constexpr (sized_range<_Range2>) { if (ranges::size(__range2) == 0) diff --git a/libcxx/include/__algorithm/ranges_count.h b/libcxx/include/__algorithm/ranges_count.h index a8965c1b961f330b1d7a8c8f0f4f717dd394bf39..4f35117438705d418992cecf12103f23cc5a3259 100644 --- a/libcxx/include/__algorithm/ranges_count.h +++ b/libcxx/include/__algorithm/ranges_count.h @@ -38,14 +38,14 @@ namespace __count { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { return std::__count<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { return std::__count<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __proj); } diff --git a/libcxx/include/__algorithm/ranges_count_if.h b/libcxx/include/__algorithm/ranges_count_if.h index 71b942dd5322b72eacb36e3f98b81ef1a40a494a..5f2396ff7d5315e07d8dba515a85f09d7b9619db 100644 --- a/libcxx/include/__algorithm/ranges_count_if.h +++ b/libcxx/include/__algorithm/ranges_count_if.h @@ -50,7 +50,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -58,7 +58,7 @@ struct __fn { template , _Proj>> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_ends_with.h b/libcxx/include/__algorithm/ranges_ends_with.h index bb01918326b8bc9496fa8cbc4b5ed19324400ab0..06efdef36b7cf22d53972f695b2a319566b3cee4 100644 --- a/libcxx/include/__algorithm/ranges_ends_with.h +++ b/libcxx/include/__algorithm/ranges_ends_with.h @@ -133,7 +133,7 @@ struct __fn { requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) && (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) && indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -152,7 +152,7 @@ struct __fn { class _Proj2 = identity> requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) && indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { auto __n1 = ranges::size(__range1); diff --git a/libcxx/include/__algorithm/ranges_equal.h b/libcxx/include/__algorithm/ranges_equal.h index 31c7ee261da61fe6381eee3ebdb067b57e930fe3..edbd0e3641c1b891a3c10ff32670ec934bbd680d 100644 --- a/libcxx/include/__algorithm/ranges_equal.h +++ b/libcxx/include/__algorithm/ranges_equal.h @@ -44,7 +44,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -74,7 +74,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) diff --git a/libcxx/include/__algorithm/ranges_equal_range.h b/libcxx/include/__algorithm/ranges_equal_range.h index 4c1c3834ba9f9f2e997a1b393fef9c4d2c496612..4a308e016b546a575d2ccafd1f8592c80bbf0871 100644 --- a/libcxx/include/__algorithm/ranges_equal_range.h +++ b/libcxx/include/__algorithm/ranges_equal_range.h @@ -46,7 +46,7 @@ struct __fn { class _Tp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__equal_range<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; @@ -56,7 +56,7 @@ struct __fn { class _Tp, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__equal_range<_RangeAlgPolicy>(ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); diff --git a/libcxx/include/__algorithm/ranges_find.h b/libcxx/include/__algorithm/ranges_find.h index 7459fad717a5d6d33cc26c7f4f396a40d805ca5f..e1383eb4b071ad965cb802f0b44e9ab91deb3ff4 100644 --- a/libcxx/include/__algorithm/ranges_find.h +++ b/libcxx/include/__algorithm/ranges_find.h @@ -52,14 +52,14 @@ struct __fn { template _Sp, class _Tp, class _Proj = identity> requires indirect_binary_predicate, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { return __find_unwrap(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { return __find_unwrap(ranges::begin(__r), ranges::end(__r), __value, __proj); } diff --git a/libcxx/include/__algorithm/ranges_find_end.h b/libcxx/include/__algorithm/ranges_find_end.h index 0bda4f3e1cea9ee7c3afac99e8bf44f0a083fcbe..e49e66dd4ac04b86f395534b11c800c2a8043220 100644 --- a/libcxx/include/__algorithm/ranges_find_end.h +++ b/libcxx/include/__algorithm/ranges_find_end.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -72,7 +72,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_find_first_of.h b/libcxx/include/__algorithm/ranges_find_first_of.h index 63a7b8335faaf5ebb5e376fc0d3276407988d0cb..d92d9686bc4420921c76ed170d19dff3a81f75c5 100644 --- a/libcxx/include/__algorithm/ranges_find_first_of.h +++ b/libcxx/include/__algorithm/ranges_find_first_of.h @@ -60,7 +60,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -78,7 +78,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __find_first_of_impl( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_find_if.h b/libcxx/include/__algorithm/ranges_find_if.h index 52ae55ce96c3664b91db68c1538b249a515d3532..888f9ec3cb2d586328a5543ba04ae67502828f0b 100644 --- a/libcxx/include/__algorithm/ranges_find_if.h +++ b/libcxx/include/__algorithm/ranges_find_if.h @@ -48,13 +48,13 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_find_if_not.h b/libcxx/include/__algorithm/ranges_find_if_not.h index 60c6796cbbfcc73ff8178eecaf0390bf72eb692c..ec19545b5a1b7a34e8d80c5aab070f51776f6bc0 100644 --- a/libcxx/include/__algorithm/ranges_find_if_not.h +++ b/libcxx/include/__algorithm/ranges_find_if_not.h @@ -40,14 +40,14 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) -> bool { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) -> bool { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj); diff --git a/libcxx/include/__algorithm/ranges_includes.h b/libcxx/include/__algorithm/ranges_includes.h index 0bc4c043bd1881406e07056efe5ae4d0b750c9b4..c4c3b8ed088d313381e462e9b5135fc13e87cc59 100644 --- a/libcxx/include/__algorithm/ranges_includes.h +++ b/libcxx/include/__algorithm/ranges_includes.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -69,7 +69,7 @@ struct __fn { class _Proj2 = identity, indirect_strict_weak_order, _Proj1>, projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return std::__includes( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_is_heap.h b/libcxx/include/__algorithm/ranges_is_heap.h index 122368c90d924d8141e0fe3299ca5ecf04e027ee..3d9e18ce1d9067806dd7acfda121caebe472fc35 100644 --- a/libcxx/include/__algorithm/ranges_is_heap.h +++ b/libcxx/include/__algorithm/ranges_is_heap.h @@ -51,7 +51,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -59,7 +59,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_is_heap_until.h b/libcxx/include/__algorithm/ranges_is_heap_until.h index b2705d37a6d3450572c997c10ddef5dc07711d0b..7a2e1fc7705b6fd81cb6e0f4a50915c805422236 100644 --- a/libcxx/include/__algorithm/ranges_is_heap_until.h +++ b/libcxx/include/__algorithm/ranges_is_heap_until.h @@ -51,7 +51,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -59,7 +59,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_is_partitioned.h b/libcxx/include/__algorithm/ranges_is_partitioned.h index c6a585c9f51070cab9ea4100c9a84574d628a688..5be6fba46fd9e247689594a7977d9637ea354114 100644 --- a/libcxx/include/__algorithm/ranges_is_partitioned.h +++ b/libcxx/include/__algorithm/ranges_is_partitioned.h @@ -57,7 +57,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __is_partitioned_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -65,7 +65,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __is_partitioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_is_permutation.h b/libcxx/include/__algorithm/ranges_is_permutation.h index e0423d722b5b9866a970c2767524560f3d18c119..1f8d67007a573820c2697c938bf668083746ced0 100644 --- a/libcxx/include/__algorithm/ranges_is_permutation.h +++ b/libcxx/include/__algorithm/ranges_is_permutation.h @@ -56,7 +56,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_equivalence_relation, projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -74,7 +74,7 @@ struct __fn { class _Proj2 = identity, indirect_equivalence_relation, _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) diff --git a/libcxx/include/__algorithm/ranges_is_sorted.h b/libcxx/include/__algorithm/ranges_is_sorted.h index d71035d5aa1d016111438133c2d521a55df44b53..5b88d422b4b091c8ec8e534ded75e1efb3995fe9 100644 --- a/libcxx/include/__algorithm/ranges_is_sorted.h +++ b/libcxx/include/__algorithm/ranges_is_sorted.h @@ -37,7 +37,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last; } @@ -45,7 +45,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __last = ranges::end(__range); return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last; diff --git a/libcxx/include/__algorithm/ranges_is_sorted_until.h b/libcxx/include/__algorithm/ranges_is_sorted_until.h index dcfb6a4e1813bdc26de8b8ab680580bbcee9959c..54de530c8b2fd8bc3d9cc72fd6310616456270fc 100644 --- a/libcxx/include/__algorithm/ranges_is_sorted_until.h +++ b/libcxx/include/__algorithm/ranges_is_sorted_until.h @@ -53,7 +53,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -61,7 +61,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_lexicographical_compare.h b/libcxx/include/__algorithm/ranges_lexicographical_compare.h index 90e96b5465169b20ac40aa2992285224eae320a9..6d82017e302a70b3f5022399517240867d5e08ed 100644 --- a/libcxx/include/__algorithm/ranges_lexicographical_compare.h +++ b/libcxx/include/__algorithm/ranges_lexicographical_compare.h @@ -60,7 +60,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -78,7 +78,7 @@ struct __fn { class _Proj2 = identity, indirect_strict_weak_order, _Proj1>, projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __lexicographical_compare_impl( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_lower_bound.h b/libcxx/include/__algorithm/ranges_lower_bound.h index ab1f80e7ab7705aaf5abec4a964feb3d9a859933..0651147e0424952f4fd82a76b35128f08e551964 100644 --- a/libcxx/include/__algorithm/ranges_lower_bound.h +++ b/libcxx/include/__algorithm/ranges_lower_bound.h @@ -43,7 +43,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); } @@ -52,7 +52,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { return std::__lower_bound<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_max.h b/libcxx/include/__algorithm/ranges_max.h index c63656de51349820e195d894d5c6576ab3ba5857..d0ee6f314b0c3f4a8258cc4bd8ecda05dd9ea477 100644 --- a/libcxx/include/__algorithm/ranges_max.h +++ b/libcxx/include/__algorithm/ranges_max.h @@ -41,7 +41,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Comp __comp = {}, @@ -52,7 +52,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); @@ -65,7 +65,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_max_element.h b/libcxx/include/__algorithm/ranges_max_element.h index 83adf49b61ad8f9f210bde074e455b6a0b30e572..c577309271165be731e810098d7ffca0e0732f21 100644 --- a/libcxx/include/__algorithm/ranges_max_element.h +++ b/libcxx/include/__algorithm/ranges_max_element.h @@ -38,7 +38,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); @@ -47,7 +47,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); diff --git a/libcxx/include/__algorithm/ranges_min.h b/libcxx/include/__algorithm/ranges_min.h index e8f97f2754acaba67ad4b0e1e70755938bf3e212..cc569d2a060c220c132b6ed7a0ae0f78d96fb6f6 100644 --- a/libcxx/include/__algorithm/ranges_min.h +++ b/libcxx/include/__algorithm/ranges_min.h @@ -40,7 +40,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Comp __comp = {}, @@ -51,7 +51,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); @@ -62,7 +62,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_min_element.h b/libcxx/include/__algorithm/ranges_min_element.h index 4b9cb76da5789c0db059444ac2a1352d1d8437bf..588ef258e26f5d746b347d01d4979b12c9bf6a14 100644 --- a/libcxx/include/__algorithm/ranges_min_element.h +++ b/libcxx/include/__algorithm/ranges_min_element.h @@ -52,7 +52,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(__first, __last, __comp, __proj); } @@ -60,7 +60,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_minmax.h b/libcxx/include/__algorithm/ranges_minmax.h index ca5722523336fdf43e6558f422425b677d40b903..09cbefd91a8c77cc5b93d10894712998ef89dcb6 100644 --- a/libcxx/include/__algorithm/ranges_minmax.h +++ b/libcxx/include/__algorithm/ranges_minmax.h @@ -52,7 +52,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result operator()(_LIBCPP_LIFETIMEBOUND const _Type& __a, _LIBCPP_LIFETIMEBOUND const _Type& __b, _Comp __comp = {}, @@ -65,7 +65,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list has to contain at least one element"); @@ -77,7 +77,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Range>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_minmax_element.h b/libcxx/include/__algorithm/ranges_minmax_element.h index 5132856ebcd5ca5a15ebca8496ad9d71eda0ef32..4bf6d2404e463d960bfed6ca4af3b9ffc8d5c754 100644 --- a/libcxx/include/__algorithm/ranges_minmax_element.h +++ b/libcxx/include/__algorithm/ranges_minmax_element.h @@ -46,7 +46,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj); return {__ret.first, __ret.second}; @@ -55,7 +55,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); return {__ret.first, __ret.second}; diff --git a/libcxx/include/__algorithm/ranges_mismatch.h b/libcxx/include/__algorithm/ranges_mismatch.h index d8a7dd43af09d5da283dfb44cd2e6203d86e1589..c4bf0022a9bcc0dd335f388bd94c75ff15293096 100644 --- a/libcxx/include/__algorithm/ranges_mismatch.h +++ b/libcxx/include/__algorithm/ranges_mismatch.h @@ -65,7 +65,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( _I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2); @@ -77,7 +77,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_R2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result, borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go( diff --git a/libcxx/include/__algorithm/ranges_none_of.h b/libcxx/include/__algorithm/ranges_none_of.h index 59bd87997d448fabc261eac64ab47e09206995f0..7df3c1829fcfcb990ff2bbc728b8e9fc07ab2b40 100644 --- a/libcxx/include/__algorithm/ranges_none_of.h +++ b/libcxx/include/__algorithm/ranges_none_of.h @@ -46,7 +46,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -54,7 +54,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_remove.h b/libcxx/include/__algorithm/ranges_remove.h index 315bed8fba775bfbc118d63910853c30bc36a495..17c3a2c5cd06b6f57a3d1fb4a7d5814e8f1d3936 100644 --- a/libcxx/include/__algorithm/ranges_remove.h +++ b/libcxx/include/__algorithm/ranges_remove.h @@ -37,7 +37,7 @@ namespace __remove { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) -> bool { return __value == __other; }; return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); @@ -46,7 +46,7 @@ struct __fn { template requires permutable> && indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) -> bool { return __value == __other; }; return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); diff --git a/libcxx/include/__algorithm/ranges_remove_if.h b/libcxx/include/__algorithm/ranges_remove_if.h index 943dbdd73807e665b8ee9a1d3e4d078a828e2492..0ea5d9a01b88183aea02bceb5d2e051112d9c639 100644 --- a/libcxx/include/__algorithm/ranges_remove_if.h +++ b/libcxx/include/__algorithm/ranges_remove_if.h @@ -59,7 +59,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -68,7 +68,7 @@ struct __fn { class _Proj = identity, indirect_unary_predicate, _Proj>> _Pred> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_search.h b/libcxx/include/__algorithm/ranges_search.h index ca2326e9ab27348cb24113ddec00ef8ae4fd2ddf..55294c60631b18964f4f679ad275fe6cbcf35344 100644 --- a/libcxx/include/__algorithm/ranges_search.h +++ b/libcxx/include/__algorithm/ranges_search.h @@ -77,7 +77,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -94,7 +94,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __first1 = ranges::begin(__range1); if constexpr (sized_range<_Range2>) { diff --git a/libcxx/include/__algorithm/ranges_search_n.h b/libcxx/include/__algorithm/ranges_search_n.h index 4c1d73d8e6c34013ee7cce5f2a9a24241626f41e..56e12755b9bf6b5d2e235e50055c8ade711cc54f 100644 --- a/libcxx/include/__algorithm/ranges_search_n.h +++ b/libcxx/include/__algorithm/ranges_search_n.h @@ -71,7 +71,7 @@ struct __fn { class _Pred = ranges::equal_to, class _Proj = identity> requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, @@ -83,7 +83,7 @@ struct __fn { template requires indirectly_comparable, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( _Range&& __range, range_difference_t<_Range> __count, const _Type& __value, _Pred __pred = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__range); diff --git a/libcxx/include/__algorithm/ranges_starts_with.h b/libcxx/include/__algorithm/ranges_starts_with.h index 7ba8af13a8d1c83084bcb227a8c145fbc7359875..17084e4f24336acbbfb20fda4a0ba5c9e604aacb 100644 --- a/libcxx/include/__algorithm/ranges_starts_with.h +++ b/libcxx/include/__algorithm/ranges_starts_with.h @@ -42,7 +42,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -67,7 +67,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { return __mismatch::__fn::__go( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h index 7340310eb36a90e210fcf9b74b73863fe9850f91..7a9b7843218737e6dc8a4a75de7d50a6fc4c8306 100644 --- a/libcxx/include/__algorithm/ranges_unique.h +++ b/libcxx/include/__algorithm/ranges_unique.h @@ -47,7 +47,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_equivalence_relation> _Comp = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); @@ -58,7 +58,7 @@ struct __fn { class _Proj = identity, indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique<_RangeAlgPolicy>( ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); diff --git a/libcxx/include/__algorithm/ranges_upper_bound.h b/libcxx/include/__algorithm/ranges_upper_bound.h index 7b571fb3448f94c7514d54b9c0782e7d2c56f12d..fa6fa7f70ed5a7316a4021bac054e1d1d5a980c4 100644 --- a/libcxx/include/__algorithm/ranges_upper_bound.h +++ b/libcxx/include/__algorithm/ranges_upper_bound.h @@ -37,7 +37,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) -> bool { return !std::invoke(__comp, __rhs, __lhs); @@ -50,7 +50,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) -> bool { return !std::invoke(__comp, __rhs, __lhs); diff --git a/libcxx/include/__algorithm/remove.h b/libcxx/include/__algorithm/remove.h index 1498852c4361308912202cea1620ae35fcb832d7..fd01c23cb6708a8ed9a9378511383b81848f8b6d 100644 --- a/libcxx/include/__algorithm/remove.h +++ b/libcxx/include/__algorithm/remove.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __first = std::find(__first, __last, __value); if (__first != __last) { diff --git a/libcxx/include/__algorithm/remove_if.h b/libcxx/include/__algorithm/remove_if.h index c77b78023f529f959ce0b2cfa35f9bd20e18abf5..b14f3c0efa7e97e4b9c20362e7a962c4ca443232 100644 --- a/libcxx/include/__algorithm/remove_if.h +++ b/libcxx/include/__algorithm/remove_if.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __first = std::find_if<_ForwardIterator, _Predicate&>(__first, __last, __pred); if (__first != __last) { diff --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h index 8557c76f80c4094edd3f0b95bb0aca45071b40b0..b82ca7809535416c4005fd2c4f97744fed439cc9 100644 --- a/libcxx/include/__algorithm/search.h +++ b/libcxx/include/__algorithm/search.h @@ -160,7 +160,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __searc } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -173,14 +173,14 @@ search(_ForwardIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::search(__first1, __last1, __first2, __last2, __equal_to()); } #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { return __s(__f, __l).first; } diff --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h index 12007fa7dea0f188cce3153280ba8f954cfd6925..771647d3168a43f03bef02f88d7ee6de0bdb154b 100644 --- a/libcxx/include/__algorithm/search_n.h +++ b/libcxx/include/__algorithm/search_n.h @@ -136,7 +136,7 @@ __search_n_impl(_Iter1 __first, _Sent1 __last, _DiffT __count, const _Type& __va } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n( _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) { static_assert( __is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, "BinaryPredicate has to be callable"); @@ -145,7 +145,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) { return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to()); } diff --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h index 056373d06fe44c5688fa474dcc7532149e598ca1..d597014596f2ea4245c70e071a3d806c95098adb 100644 --- a/libcxx/include/__algorithm/unique.h +++ b/libcxx/include/__algorithm/unique.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unique template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { __first = std::__adjacent_find(__first, __last, __pred); if (__first != __last) { @@ -46,13 +46,13 @@ __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last) { return std::unique(__first, __last, __equal_to()); } diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h index 9c7d8fbcde07b5ac6bb2f429bb47da236029cbcf..c39dec2e89698247a20678edf575690aceef9f11 100644 --- a/libcxx/include/__algorithm/upper_bound.h +++ b/libcxx/include/__algorithm/upper_bound.h @@ -48,7 +48,7 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); return std::__upper_bound<_ClassicAlgPolicy>( @@ -56,7 +56,7 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::upper_bound(std::move(__first), std::move(__last), __value, __less<>()); } diff --git a/libcxx/include/__bit/bit_cast.h b/libcxx/include/__bit/bit_cast.h index 6298810f3733031fa45d23ca165a138cb21864b5..cd0456738179326923610cac599e8ed53ebe07a3 100644 --- a/libcxx/include/__bit/bit_cast.h +++ b/libcxx/include/__bit/bit_cast.h @@ -33,7 +33,7 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr _ToType __bit_cast(const _From template requires(sizeof(_ToType) == sizeof(_FromType) && is_trivially_copyable_v<_ToType> && is_trivially_copyable_v<_FromType>) -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { return __builtin_bit_cast(_ToType, __from); } diff --git a/libcxx/include/__bit/bit_ceil.h b/libcxx/include/__bit/bit_ceil.h index 77fa739503bc58c0ca5d39574d4aa5169a81a608..cfd792dc2e2adbd04f0a1dc2177e06ec6d30e146 100644 --- a/libcxx/include/__bit/bit_ceil.h +++ b/libcxx/include/__bit/bit_ceil.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - std::__countl_zero((_Tp)(__t - 1u)); @@ -42,7 +42,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) no # if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { return std::__bit_ceil(__t); } diff --git a/libcxx/include/__bit/bit_floor.h b/libcxx/include/__bit/bit_floor.h index cf5cf5803ad64fe9b617ddfc2ed8c7e5b864823e..133e369504e431c137505bf48affd394eb2c5bdb 100644 --- a/libcxx/include/__bit/bit_floor.h +++ b/libcxx/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); } diff --git a/libcxx/include/__bit/bit_width.h b/libcxx/include/__bit/bit_width.h index a2020a01421e321d54c026f4c36ebcdf2911ba28..853e481776f7d2d2e705a978fa26ce5365072896 100644 --- a/libcxx/include/__bit/bit_width.h +++ b/libcxx/include/__bit/bit_width.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : std::__bit_log2(__t) + 1; } diff --git a/libcxx/include/__bit/byteswap.h b/libcxx/include/__bit/byteswap.h index 20045d6fd43cb57a1e41f1a0356b5067f3d38cdd..6225ecf2f92dfb4fff1146e73a7272ccf2af7e1d 100644 --- a/libcxx/include/__bit/byteswap.h +++ b/libcxx/include/__bit/byteswap.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { if constexpr (sizeof(_Tp) == 1) { return __val; } else if constexpr (sizeof(_Tp) == 2) { diff --git a/libcxx/include/__bit/countl.h b/libcxx/include/__bit/countl.h index 13df8d4e66c402610114bf5d3bb71f7231ae38f1..998a0b44c19dcb90fa4614fe309cadb19a9e1eb6 100644 --- a/libcxx/include/__bit/countl.h +++ b/libcxx/include/__bit/countl.h @@ -95,12 +95,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/countr.h b/libcxx/include/__bit/countr.h index 724a0bc23801c49f13438f9678894a67e7467cdb..9e92021fba355188732e130c3449bf8b57dbe039 100644 --- a/libcxx/include/__bit/countr.h +++ b/libcxx/include/__bit/countr.h @@ -66,12 +66,12 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __coun #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { return std::__countr_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/has_single_bit.h b/libcxx/include/__bit/has_single_bit.h index a4e178060a73a3830de869649256a14f66122957..52f5853a1bc8a4092c636db0d5c4d683a9733f51 100644 --- a/libcxx/include/__bit/has_single_bit.h +++ b/libcxx/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { return __t != 0 && (((__t & (__t - 1)) == 0)); } diff --git a/libcxx/include/__bit/popcount.h b/libcxx/include/__bit/popcount.h index 37b3a3e1f3f2b92d26c369d2729cf705d1ea60d7..5cf0a01d0733823c9708c4a9a11c50bc1a091f6c 100644 --- a/libcxx/include/__bit/popcount.h +++ b/libcxx/include/__bit/popcount.h @@ -41,7 +41,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned lo #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { # if __has_builtin(__builtin_popcountg) return __builtin_popcountg(__t); # else // __has_builtin(__builtin_popcountg) diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index f7256db3bea661101d5f5c2536fa21bbf1dce861..881a4970822d8e0bcb44e24865353f3247b8d1c0 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -173,7 +173,7 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { if (__value.hours().count() > std::numeric_limits::max()) std::__throw_format_error("Formatting hh_mm_ss, encountered an hour overflow"); __result.tm_hour = __value.hours().count(); -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) } else if constexpr (same_as<_ChronoT, chrono::sys_info>) { // Has no time information. } else if constexpr (same_as<_ChronoT, chrono::local_info>) { diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 6a14c344fa1188c0cbd71289d0562d93c6c6a1f2..e9b81c3de8a700bbf49983a2b5f544585cc922ea 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -88,6 +88,9 @@ __format_sub_seconds(basic_stringstream<_CharT>& __sstr, const chrono::duration< using __duration = chrono::duration<_Rep, _Period>; auto __fraction = __value - chrono::duration_cast(__value); + // Converts a negative fraction to its positive value. + if (__value < chrono::seconds{0} && __fraction != __duration{0}) + __fraction += chrono::seconds{1}; if constexpr (chrono::treat_as_floating_point_v<_Rep>) // When the floating-point value has digits itself they are ignored based // on the wording in [tab:time.format.spec] @@ -205,7 +208,7 @@ struct _LIBCPP_HIDE_FROM_ABI __time_zone { template _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const _Tp& __value) { -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) if constexpr (same_as<_Tp, chrono::sys_info>) return {__value.abbrev, __value.offset}; else @@ -417,7 +420,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -463,7 +466,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -509,7 +512,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { return __value.ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -555,7 +558,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { return __value.month().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -891,7 +894,7 @@ public: } }; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) template <__fmt_char_type _CharT> struct formatter : public __formatter_chrono<_CharT> { public: @@ -913,7 +916,7 @@ public: return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags{}); } }; -# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__chrono/leap_second.h b/libcxx/include/__chrono/leap_second.h index 557abc15ff18470eb186111975e9d4acff483246..1a0e7f3107de81aa8b696fb324b2525099d3684c 100644 --- a/libcxx/include/__chrono/leap_second.h +++ b/libcxx/include/__chrono/leap_second.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/system_clock.h> @@ -43,9 +43,9 @@ public: _LIBCPP_HIDE_FROM_ABI leap_second(const leap_second&) = default; _LIBCPP_HIDE_FROM_ABI leap_second& operator=(const leap_second&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; } private: sys_seconds __date_; @@ -121,6 +121,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const leap_second& __x, const s _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_LEAP_SECOND_H diff --git a/libcxx/include/__chrono/local_info.h b/libcxx/include/__chrono/local_info.h index b1a03ad7df2acab44fce1b44b04aff84ef372e97..cfe1448904d3f77831340bcad50e7fa3f6347828 100644 --- a/libcxx/include/__chrono/local_info.h +++ b/libcxx/include/__chrono/local_info.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/sys_info.h> # include <__config> @@ -45,6 +45,6 @@ struct local_info { _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_LOCAL_INFO_H diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h index cb17dbea58bee3606014379ac0c69596f92b0945..ecf07a320c8b945e68edae1cfbc8f15cf68e9543 100644 --- a/libcxx/include/__chrono/ostream.h +++ b/libcxx/include/__chrono/ostream.h @@ -264,7 +264,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const hh_mm_ss<_Duration> __hms return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%T}"), __hms); } -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) template _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& @@ -302,7 +302,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __info) { _LIBCPP_STATICALLY_WIDEN(_CharT, "{}: {{{}, {}}}"), __result(), __info.first, __info.second); } -# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) } // namespace chrono diff --git a/libcxx/include/__chrono/sys_info.h b/libcxx/include/__chrono/sys_info.h index 461d5322d413b3a4bf3c2ec2be2b41532f34f6b8..11536cbde3a37c481cd0fce344f040708f5503a4 100644 --- a/libcxx/include/__chrono/sys_info.h +++ b/libcxx/include/__chrono/sys_info.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/system_clock.h> @@ -46,6 +46,6 @@ struct sys_info { _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_SYS_INFO_H diff --git a/libcxx/include/__chrono/time_zone.h b/libcxx/include/__chrono/time_zone.h index 8e30034b799ad9feea959942988ac9fd565feed3..91ddab8903fe219b235825dacaa08ee036302f17 100644 --- a/libcxx/include/__chrono/time_zone.h +++ b/libcxx/include/__chrono/time_zone.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/sys_info.h> @@ -56,10 +56,10 @@ public: _LIBCPP_HIDE_FROM_ABI time_zone(time_zone&&) = default; _LIBCPP_HIDE_FROM_ABI time_zone& operator=(time_zone&&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); } template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const { return __get_info(chrono::time_point_cast(__time)); } @@ -73,12 +73,12 @@ private: unique_ptr<__impl> __impl_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool operator==(const time_zone& __x, const time_zone& __y) noexcept { return __x.name() == __y.name(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering operator<=>(const time_zone& __x, const time_zone& __y) noexcept { return __x.name() <=> __y.name(); } @@ -92,6 +92,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TIME_ZONE_H diff --git a/libcxx/include/__chrono/time_zone_link.h b/libcxx/include/__chrono/time_zone_link.h index c76ddeff9f966d020b0d4ed29990322a387194aa..b2d365c5fd0820db7076fa1f4bb0c3d0563f9d4b 100644 --- a/libcxx/include/__chrono/time_zone_link.h +++ b/libcxx/include/__chrono/time_zone_link.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__compare/strong_order.h> # include <__config> @@ -38,15 +38,15 @@ namespace chrono { class time_zone_link { public: - _LIBCPP_NODISCARD_EXT + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit time_zone_link(__private_constructor_tag, string_view __name, string_view __target) : __name_{__name}, __target_{__target} {} _LIBCPP_HIDE_FROM_ABI time_zone_link(time_zone_link&&) = default; _LIBCPP_HIDE_FROM_ABI time_zone_link& operator=(time_zone_link&&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name_; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view target() const noexcept { return __target_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view target() const noexcept { return __target_; } private: string __name_; @@ -56,12 +56,12 @@ private: string __target_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool operator==(const time_zone_link& __x, const time_zone_link& __y) noexcept { return __x.name() == __y.name(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering operator<=>(const time_zone_link& __x, const time_zone_link& __y) noexcept { return __x.name() <=> __y.name(); } @@ -74,6 +74,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TIME_ZONE_LINK_H diff --git a/libcxx/include/__chrono/tzdb.h b/libcxx/include/__chrono/tzdb.h index e0bfedf0d78239e65dd883886e09b9d83aeda5a7..f731f8c318be079ab251014963636b9eda5c4a6c 100644 --- a/libcxx/include/__chrono/tzdb.h +++ b/libcxx/include/__chrono/tzdb.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__algorithm/ranges_lower_bound.h> # include <__chrono/leap_second.h> @@ -57,14 +57,14 @@ struct tzdb { return nullptr; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const { if (const time_zone* __result = __locate_zone(__name)) return __result; std::__throw_runtime_error("tzdb: requested time zone not found"); } - _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const { + [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const { return __current_zone(); } @@ -89,6 +89,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TZDB_H diff --git a/libcxx/include/__chrono/tzdb_list.h b/libcxx/include/__chrono/tzdb_list.h index 693899d372112dead062faa49eca871ace8b2ea9..62db7e3d2e0b5e3597e7cd3f30bfd0e2140d8971 100644 --- a/libcxx/include/__chrono/tzdb_list.h +++ b/libcxx/include/__chrono/tzdb_list.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__availability> # include <__chrono/time_zone.h> @@ -53,15 +53,15 @@ public: using const_iterator = forward_list::const_iterator; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } _LIBCPP_HIDE_FROM_ABI const_iterator erase_after(const_iterator __p) { return __erase_after(__p); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return __cbegin(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return __cbegin(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __impl& __implementation() { return *__impl_; } @@ -79,24 +79,23 @@ private: __impl* __impl_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list(); +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list(); -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const tzdb& get_tzdb() { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const tzdb& get_tzdb() { return get_tzdb_list().front(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* -locate_zone(string_view __name) { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* locate_zone(string_view __name) { return get_tzdb().locate_zone(__name); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() { return get_tzdb().current_zone(); } _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb(); -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version(); +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version(); } // namespace chrono @@ -105,6 +104,6 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TZDB_LIST_H diff --git a/libcxx/include/__config b/libcxx/include/__config index 4ccef2ca0d73b4d42c1de5c1f95ec06ea50b56ae..97cdd020c55d1f5d3c3c7d6ee6cb923631164c7b 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -421,7 +421,7 @@ _LIBCPP_HARDENING_MODE_DEBUG # if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) # define _LIBCPP_HAS_NO_INCOMPLETE_PSTL # define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN -# define _LIBCPP_HAS_NO_INCOMPLETE_TZDB +# define _LIBCPP_HAS_NO_EXPERIMENTAL_TZDB # define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM # endif @@ -1375,7 +1375,7 @@ typedef __char32_t char32_t; # define _LIBCPP_USING_IF_EXISTS # endif -# if __has_cpp_attribute(nodiscard) +# if __has_cpp_attribute(__nodiscard__) # define _LIBCPP_NODISCARD [[__nodiscard__]] # else // We can't use GCC's [[gnu::warn_unused_result]] and @@ -1384,20 +1384,6 @@ typedef __char32_t char32_t; # define _LIBCPP_NODISCARD # endif -// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not -// specified as such as an extension. -# if !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_EXT -# endif - -# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_AFTER_CXX17 -# endif - # if __has_attribute(__no_destroy__) # define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) # else diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 9ffc90ada5e716d120ddb22aab484daef449ed40..89d319b4b19b57c77743ce08e14475e08418c8bf 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -812,7 +812,7 @@ public: _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); } // query - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); } _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); } _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); } diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h index c7810140105a07225e522d9719e61a385815003f..d14b49aff149573e85cdff3ac2b7cbd5bcd5341d 100644 --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -66,14 +66,13 @@ using wformat_args = basic_format_args; # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { return std::__format_arg_store<_Context, _Args...>(__args...); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store -make_wformat_args(_Args&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store make_wformat_args(_Args&... __args) { return std::__format_arg_store(__args...); } # endif @@ -452,8 +451,7 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string -vformat(string_view __fmt, format_args __args) { +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { string __res; std::vformat_to(std::back_inserter(__res), __fmt, __args); return __res; @@ -463,7 +461,7 @@ vformat(string_view __fmt, format_args __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { wstring __res; std::vformat_to(std::back_inserter(__res), __fmt, __args); @@ -472,14 +470,14 @@ vformat(wstring_view __fmt, wformat_args __args) { # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_format_args(__args...)); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(wformat_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); } @@ -520,14 +518,14 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, } template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); } @@ -585,7 +583,7 @@ format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&& // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(locale __loc, string_view __fmt, format_args __args) { string __res; std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); @@ -596,7 +594,7 @@ vformat(locale __loc, string_view __fmt, format_args __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(locale __loc, wstring_view __fmt, wformat_args __args) { wstring __res; std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); @@ -605,14 +603,14 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) { # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); } @@ -658,14 +656,14 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ } template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); } diff --git a/libcxx/include/__functional/identity.h b/libcxx/include/__functional/identity.h index b7be367bd5eed7a4fa05d22dbc849040dc73275c..8468de3dae26c2ca4a1657a1f23688c684afc699 100644 --- a/libcxx/include/__functional/identity.h +++ b/libcxx/include/__functional/identity.h @@ -44,7 +44,7 @@ struct __is_identity > : true_type {}; struct identity { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { return std::forward<_Tp>(__t); } diff --git a/libcxx/include/__iterator/empty.h b/libcxx/include/__iterator/empty.h index 3ca0aff6be46efb2ea7c19a241ec1cf55a4f9312..773f2776955b2a16707e1805e40967e35757cbef 100644 --- a/libcxx/include/__iterator/empty.h +++ b/libcxx/include/__iterator/empty.h @@ -23,18 +23,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr auto empty(const _Cont& __c) - _NOEXCEPT_(noexcept(__c.empty())) -> decltype(__c.empty()) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto +empty(const _Cont& __c) noexcept(noexcept(__c.empty())) -> decltype(__c.empty()) { return __c.empty(); } template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr bool empty(const _Tp (&)[_Sz]) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty(const _Tp (&)[_Sz]) noexcept { return false; } template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr bool empty(initializer_list<_Ep> __il) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } diff --git a/libcxx/include/__math/abs.h b/libcxx/include/__math/abs.h index 6004690f4c4f4c352190a5d2ad5ca1c55590e508..ab82a2800f53c918c5cdf6cdfc9ade264167f245 100644 --- a/libcxx/include/__math/abs.h +++ b/libcxx/include/__math/abs.h @@ -23,19 +23,19 @@ namespace __math { // fabs -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { return __builtin_fabs(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT { return __builtin_fabsl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double fabs(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double fabs(_A1 __x) _NOEXCEPT { return __builtin_fabs((double)__x); } diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h index 2219297e8b8c1eae2fb06acff1151eaf5a94d7ea..b38690bb581a1155325bf9a25d4e2a4399a8e7b2 100644 --- a/libcxx/include/__math/copysign.h +++ b/libcxx/include/__math/copysign.h @@ -25,17 +25,16 @@ namespace __math { // copysign -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { return ::__builtin_copysignf(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { return ::__builtin_copysignl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type -copysign(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { return ::__builtin_copysign(__x, __y); } diff --git a/libcxx/include/__math/min_max.h b/libcxx/include/__math/min_max.h index 381b2af4a56cf0c705e180eb98873e00a9673820..c2c4f6b645609ce9b9d1b85f653573b927ac5993 100644 --- a/libcxx/include/__math/min_max.h +++ b/libcxx/include/__math/min_max.h @@ -25,21 +25,21 @@ namespace __math { // fmax -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { return __builtin_fmaxf(__x, __y); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { return __builtin_fmax(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT { return __builtin_fmaxl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); return __math::fmax((__result_type)__x, (__result_type)__y); @@ -47,21 +47,21 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>: // fmin -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT { return __builtin_fminf(__x, __y); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { return __builtin_fmin(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT { return __builtin_fminl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); return __math::fmin((__result_type)__x, (__result_type)__y); diff --git a/libcxx/include/__math/roots.h b/libcxx/include/__math/roots.h index faee688bc95b82530feef87676233e2157d9ce16..359fd747cfbef396cc28b42784fcd67c027344c7 100644 --- a/libcxx/include/__math/roots.h +++ b/libcxx/include/__math/roots.h @@ -39,19 +39,19 @@ inline _LIBCPP_HIDE_FROM_ABI double sqrt(_A1 __x) _NOEXCEPT { // cbrt -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT { return __builtin_cbrtf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT { return __builtin_cbrtf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { return __builtin_cbrt(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT { return __builtin_cbrtl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double cbrt(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double cbrt(_A1 __x) _NOEXCEPT { return __builtin_cbrt((double)__x); } diff --git a/libcxx/include/__math/rounding_functions.h b/libcxx/include/__math/rounding_functions.h index 29e42fd80b00d60f984cd82124927cb155a6015a..33e6cbc37d604ccdbc7c656d2f3790b5f3bd03cf 100644 --- a/libcxx/include/__math/rounding_functions.h +++ b/libcxx/include/__math/rounding_functions.h @@ -26,37 +26,37 @@ namespace __math { // ceil -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT { return __builtin_ceilf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT { return __builtin_ceilf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { return __builtin_ceil(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT { return __builtin_ceill(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double ceil(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double ceil(_A1 __x) _NOEXCEPT { return __builtin_ceil((double)__x); } // floor -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT { return __builtin_floorf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT { return __builtin_floorf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { return __builtin_floor(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT { return __builtin_floorl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double floor(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double floor(_A1 __x) _NOEXCEPT { return __builtin_floor((double)__x); } @@ -126,21 +126,21 @@ inline _LIBCPP_HIDE_FROM_ABI long lround(_A1 __x) _NOEXCEPT { // nearbyint -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT { return __builtin_nearbyintf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { return __builtin_nearbyint(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT { return __builtin_nearbyintl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double nearbyint(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double nearbyint(_A1 __x) _NOEXCEPT { return __builtin_nearbyint((double)__x); } @@ -186,55 +186,55 @@ inline _LIBCPP_HIDE_FROM_ABI double nexttoward(_A1 __x, long double __y) _NOEXCE // rint -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { return __builtin_rint(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { return __builtin_rintl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double rint(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double rint(_A1 __x) _NOEXCEPT { return __builtin_rint((double)__x); } // round -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_round(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_round(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { return __builtin_round(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { return __builtin_roundl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double round(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double round(_A1 __x) _NOEXCEPT { return __builtin_round((double)__x); } // trunc -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_trunc(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_trunc(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { return __builtin_trunc(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { return __builtin_truncl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double trunc(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double trunc(_A1 __x) _NOEXCEPT { return __builtin_trunc((double)__x); } diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index da585af8837f0cbe9af67cb79cd9dd362ace78b7..a4482667975576cb3bc8b94d5b42d3788f46a49f 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -29,55 +29,55 @@ namespace __math { // signbit template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __builtin_signbit(__x); } template ::value && is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } template ::value && !is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { return false; } // isfinite template ::value && numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { return __builtin_isfinite((typename __promote<_A1>::type)__x); } template ::value && !numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { return true; } // isinf template ::value && numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { return __builtin_isinf((typename __promote<_A1>::type)__x); } template ::value && !numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { return false; } #ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { return __builtin_isinf(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT { return __builtin_isinf(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { return __builtin_isinf(__x); } #endif @@ -85,26 +85,26 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI // isnan template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { return __builtin_isnan(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { return false; } #ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { return __builtin_isnan(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT { return __builtin_isnan(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { return __builtin_isnan(__x); } #endif @@ -112,19 +112,19 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI // isnormal template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __builtin_isnormal(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __x != 0; } // isgreater template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isgreater((type)__x, (type)__y); } @@ -132,7 +132,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 _ // isgreaterequal template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isgreaterequal((type)__x, (type)__y); } @@ -140,7 +140,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, // isless template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isless((type)__x, (type)__y); } @@ -148,7 +148,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) // islessequal template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_islessequal((type)__x, (type)__y); } @@ -156,7 +156,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 // islessgreater template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_islessgreater((type)__x, (type)__y); } @@ -164,7 +164,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _ // isunordered template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isunordered((type)__x, (type)__y); } diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h index 26e5d4978b151e0830c6334935ce0e7e210b9280..215d3832f9ef341de1a13326af11ad08cb21d53f 100644 --- a/libcxx/include/__memory/allocator.h +++ b/libcxx/include/__memory/allocator.h @@ -110,7 +110,7 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { @@ -153,8 +153,7 @@ public: return std::addressof(__x); } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 _Tp* - allocate(size_t __n, const void*) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 _Tp* allocate(size_t __n, const void*) { return allocate(__n); } @@ -190,7 +189,7 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const _Tp* allocate(size_t __n) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { @@ -230,8 +229,7 @@ public: return std::addressof(__x); } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 const _Tp* - allocate(size_t __n, const void*) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 const _Tp* allocate(size_t __n, const void*) { return allocate(__n); } diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index 7b3deb0f58e950cecf0adfa46d583202713ac1c4..47fe132d15cb1f82bab97fb99ffe1d9c21c764d3 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -275,13 +275,13 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits { }; #endif // _LIBCPP_CXX03_LANG - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n) { return __a.allocate(__n); } template ::value, int> = 0> - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) { _LIBCPP_SUPPRESS_DEPRECATED_PUSH return __a.allocate(__n, __hint); @@ -290,7 +290,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits { template ::value, int> = 0> - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer) { return __a.allocate(__n); } diff --git a/libcxx/include/__memory/temporary_buffer.h b/libcxx/include/__memory/temporary_buffer.h index e3797caff8c9f2065401960fa003d0db633d81ea..88799ca95c1f352c80698661ee3c4738c77cf902 100644 --- a/libcxx/include/__memory/temporary_buffer.h +++ b/libcxx/include/__memory/temporary_buffer.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t> get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT { pair<_Tp*, ptrdiff_t> __r(0, 0); const ptrdiff_t __m = diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h index 9b7262bec5cf8bfe7a03515782ad8b6ceeec4c8f..5e5819d4c281e4c462a702c6503b988512196f31 100644 --- a/libcxx/include/__memory/uses_allocator_construction.h +++ b/libcxx/include/__memory/uses_allocator_construction.h @@ -184,20 +184,18 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Type&& __value) noexc struct __pair_constructor { using _PairMutable = remove_cv_t<_Pair>; - _LIBCPP_HIDE_FROM_ABI constexpr auto __do_construct(const _PairMutable& __pair) const { + _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const { return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair); } - _LIBCPP_HIDE_FROM_ABI constexpr auto __do_construct(_PairMutable&& __pair) const { + _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const { return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair)); } const _Alloc& __alloc_; _Type& __value_; - _LIBCPP_HIDE_FROM_ABI constexpr operator _PairMutable() const { - return __do_construct(std::forward<_Type>(this->__value_)); - } + _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); } }; return std::make_tuple(__pair_constructor{__alloc, __value}); diff --git a/libcxx/include/__memory_resource/memory_resource.h b/libcxx/include/__memory_resource/memory_resource.h index 418f36dc9b390d729d4aa967f64bc98b9599d4d2..e605838bf5ea4096b270352daaf1f884a493e3c8 100644 --- a/libcxx/include/__memory_resource/memory_resource.h +++ b/libcxx/include/__memory_resource/memory_resource.h @@ -32,9 +32,8 @@ class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource { public: virtual ~memory_resource(); - _LIBCPP_NODISCARD_AFTER_CXX17 - [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void* - allocate(size_t __bytes, size_t __align = __max_align) { + [[nodiscard]] [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] + _LIBCPP_HIDE_FROM_ABI void* allocate(size_t __bytes, size_t __align = __max_align) { return do_allocate(__bytes, __align); } diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h index 823c1503c22b65be76098614ee0cee2fc6fbff78..8fda201124387e82dcebdac05b14eebab2959000 100644 --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -61,7 +61,7 @@ public: // [mem.poly.allocator.mem] - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { if (__n > __max_size()) { __throw_bad_array_new_length(); } diff --git a/libcxx/include/__mutex/lock_guard.h b/libcxx/include/__mutex/lock_guard.h index c075512fb97a95bdb9f13710ece20c50532101b7..739d1683b317b0a1a37c5928c39b88076b53b6c5 100644 --- a/libcxx/include/__mutex/lock_guard.h +++ b/libcxx/include/__mutex/lock_guard.h @@ -29,13 +29,13 @@ private: mutex_type& __m_; public: - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) - _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + _LIBCPP_NODISCARD + _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) { __m_.lock(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index 24d2624c37394618c0a69340ed9fcf0ebb480712..d0b35bfd193409d0c868369db84aff4c15dc3711 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -147,7 +147,7 @@ public: _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) { diff --git a/libcxx/include/__random/linear_congruential_engine.h b/libcxx/include/__random/linear_congruential_engine.h index fe9cb909b74d21a3134452a6356d1363dcf6af4a..9d77649e9cfc8e04b4f778d15b6f2100a9694f36 100644 --- a/libcxx/include/__random/linear_congruential_engine.h +++ b/libcxx/include/__random/linear_congruential_engine.h @@ -26,32 +26,60 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +enum __lce_alg_type { + _LCE_Full, + _LCE_Part, + _LCE_Schrage, + _LCE_Promote, +}; + template (_Mp - __c) / __a), - bool _OverflowOK = ((__m & (__m - 1)) == 0ull), // m = 2^n - bool _SchrageOK = (__a != 0 && __m != 0 && __m % __a <= __m / __a)> // r <= q + bool _HasOverflow = (__a != 0ull && (__m & (__m - 1ull)) != 0ull), // a != 0, m != 0, m != 2^n + bool _Full = (!_HasOverflow || __m - 1ull <= (_Mp - __c) / __a), // (a * x + c) % m works + bool _Part = (!_HasOverflow || __m - 1ull <= _Mp / __a), // (a * x) % m works + bool _Schrage = (_HasOverflow && __m % __a <= __m / __a)> // r <= q struct __lce_alg_picker { - static_assert(!_MightOverflow || _OverflowOK || _SchrageOK, - "The current values of a, c, and m cannot generate a number " - "within bounds of linear_congruential_engine."); - - static _LIBCPP_CONSTEXPR const bool __use_schrage = _MightOverflow && !_OverflowOK && _SchrageOK; + static _LIBCPP_CONSTEXPR const __lce_alg_type __mode = + _Full ? _LCE_Full + : _Part ? _LCE_Part + : _Schrage ? _LCE_Schrage + : _LCE_Promote; + +#ifdef _LIBCPP_HAS_NO_INT128 + static_assert(_Mp != (unsigned long long)(-1) || _Full || _Part || _Schrage, + "The current values for a, c, and m are not currently supported on platforms without __int128"); +#endif }; template ::__use_schrage> + __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode> struct __lce_ta; // 64 +#ifndef _LIBCPP_HAS_NO_INT128 +template +struct __lce_ta<_Ap, _Cp, _Mp, (unsigned long long)(-1), _LCE_Promote> { + typedef unsigned long long result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __xp) { + __extension__ using __calc_type = unsigned __int128; + const __calc_type __a = static_cast<__calc_type>(_Ap); + const __calc_type __c = static_cast<__calc_type>(_Cp); + const __calc_type __m = static_cast<__calc_type>(_Mp); + const __calc_type __x = static_cast<__calc_type>(__xp); + return static_cast((__a * __x + __c) % __m); + } +}; +#endif + template -struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), true> { +struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Schrage> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { // Schrage's algorithm @@ -66,7 +94,7 @@ struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), true> { }; template -struct __lce_ta<__a, 0, __m, (unsigned long long)(~0), true> { +struct __lce_ta<__a, 0ull, __m, (unsigned long long)(-1), _LCE_Schrage> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { // Schrage's algorithm @@ -80,21 +108,40 @@ struct __lce_ta<__a, 0, __m, (unsigned long long)(~0), true> { }; template -struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), false> { +struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Part> { + typedef unsigned long long result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { + // Use (((a*x) % m) + c) % m + __x = (__a * __x) % __m; + __x += __c - (__x >= __m - __c) * __m; + return __x; + } +}; + +template +struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Full> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return (__a * __x + __c) % __m; } }; template -struct __lce_ta<__a, __c, 0, (unsigned long long)(~0), false> { +struct __lce_ta<__a, __c, 0ull, (unsigned long long)(-1), _LCE_Full> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return __a * __x + __c; } }; // 32 +template +struct __lce_ta<__a, __c, __m, unsigned(-1), _LCE_Promote> { + typedef unsigned result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { + return static_cast(__lce_ta<__a, __c, __m, (unsigned long long)(-1)>::next(__x)); + } +}; + template -struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), true> { +struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Schrage> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -112,7 +159,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), true> { }; template -struct __lce_ta<_Ap, 0, _Mp, unsigned(~0), true> { +struct __lce_ta<_Ap, 0ull, _Mp, unsigned(-1), _LCE_Schrage> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -128,7 +175,21 @@ struct __lce_ta<_Ap, 0, _Mp, unsigned(~0), true> { }; template -struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), false> { +struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Part> { + typedef unsigned result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { + const result_type __a = static_cast(_Ap); + const result_type __c = static_cast(_Cp); + const result_type __m = static_cast(_Mp); + // Use (((a*x) % m) + c) % m + __x = (__a * __x) % __m; + __x += __c - (__x >= __m - __c) * __m; + return __x; + } +}; + +template +struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Full> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -139,7 +200,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), false> { }; template -struct __lce_ta<_Ap, _Cp, 0, unsigned(~0), false> { +struct __lce_ta<_Ap, _Cp, 0ull, unsigned(-1), _LCE_Full> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -150,11 +211,11 @@ struct __lce_ta<_Ap, _Cp, 0, unsigned(~0), false> { // 16 -template -struct __lce_ta<__a, __c, __m, (unsigned short)(~0), __b> { +template +struct __lce_ta<__a, __c, __m, (unsigned short)(-1), __mode> { typedef unsigned short result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { - return static_cast(__lce_ta<__a, __c, __m, unsigned(~0)>::next(__x)); + return static_cast(__lce_ta<__a, __c, __m, unsigned(-1)>::next(__x)); } }; @@ -178,7 +239,7 @@ public: private: result_type __x_; - static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(~0); + static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(-1); static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters"); static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters"); diff --git a/libcxx/include/__ranges/as_rvalue_view.h b/libcxx/include/__ranges/as_rvalue_view.h index 2fc272e798d6e0a9be5f05c7885315fe2efaebf6..5849a6c3683960ef804bf79b9d496e76daae8737 100644 --- a/libcxx/include/__ranges/as_rvalue_view.h +++ b/libcxx/include/__ranges/as_rvalue_view.h @@ -111,7 +111,7 @@ namespace views { namespace __as_rvalue { struct __fn : __range_adaptor_closure<__fn> { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range) noexcept(noexcept(as_rvalue_view(std::forward<_Range>(__range)))) -> decltype(/*--------------------------*/ as_rvalue_view(std::forward<_Range>(__range))) { return /*---------------------------------*/ as_rvalue_view(std::forward<_Range>(__range)); @@ -119,7 +119,7 @@ struct __fn : __range_adaptor_closure<__fn> { template requires same_as, range_reference_t<_Range>> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range) noexcept(noexcept(views::all(std::forward<_Range>(__range)))) -> decltype(/*--------------------------*/ views::all(std::forward<_Range>(__range))) { return /*---------------------------------*/ views::all(std::forward<_Range>(__range)); diff --git a/libcxx/include/__ranges/chunk_by_view.h b/libcxx/include/__ranges/chunk_by_view.h index b04a23de99fb2a756158fb6e83f86f5e4f9bd41a..00014d9f10ae8865a913e8aedf54b066803124eb 100644 --- a/libcxx/include/__ranges/chunk_by_view.h +++ b/libcxx/include/__ranges/chunk_by_view.h @@ -205,7 +205,7 @@ namespace views { namespace __chunk_by { struct __fn { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const noexcept(noexcept(/**/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)))) -> decltype(/*--*/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) { return /*-------------*/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)); @@ -213,7 +213,7 @@ struct __fn { template requires constructible_from, _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const noexcept(is_nothrow_constructible_v, _Pred>) { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred))); } diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h index 83bb598b0a0c916c9420301775d4b4f19471467d..fbfbca4db62186b135bf5ab375a190ffdb658766 100644 --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -266,7 +266,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires (__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept(views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) -> decltype( views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { return views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } @@ -277,7 +277,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires (__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&&) const noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) diff --git a/libcxx/include/__ranges/range_adaptor.h b/libcxx/include/__ranges/range_adaptor.h index 726b7eda019ee3abc8098bf7e682f74978bb3c1a..2da246f24e1d2f2a782e95bfdf5f521ef234cd94 100644 --- a/libcxx/include/__ranges/range_adaptor.h +++ b/libcxx/include/__ranges/range_adaptor.h @@ -19,6 +19,7 @@ #include <__functional/invoke.h> #include <__ranges/concepts.h> #include <__type_traits/decay.h> +#include <__type_traits/is_class.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/remove_cvref.h> #include <__utility/forward.h> @@ -35,12 +36,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 +namespace ranges { + // CRTP base that one can derive from in order to be considered a range adaptor closure // by the library. When deriving from this class, a pipe operator will be provided to // make the following hold: // - `x | f` is equivalent to `f(x)` // - `f1 | f2` is an adaptor closure `g` such that `g(x)` is equivalent to `f2(f1(x))` template + requires is_class_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> struct __range_adaptor_closure; // Type that wraps an arbitrary function object and makes it into a range adaptor closure, @@ -52,27 +56,42 @@ struct __range_adaptor_closure_t : _Fn, __range_adaptor_closure<__range_adaptor_ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__range_adaptor_closure_t); template -concept _RangeAdaptorClosure = derived_from, __range_adaptor_closure>>; +_Tp __derived_from_range_adaptor_closure(__range_adaptor_closure<_Tp>*); template -struct __range_adaptor_closure { - template - requires same_as<_Tp, remove_cvref_t<_Closure>> && invocable<_Closure, _View> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto) - operator|(_View&& __view, _Closure&& __closure) noexcept(is_nothrow_invocable_v<_Closure, _View>) { - return std::invoke(std::forward<_Closure>(__closure), std::forward<_View>(__view)); - } - - template <_RangeAdaptorClosure _Closure, _RangeAdaptorClosure _OtherClosure> - requires same_as<_Tp, remove_cvref_t<_Closure>> && constructible_from, _Closure> && - constructible_from, _OtherClosure> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator|(_Closure&& __c1, _OtherClosure&& __c2) noexcept( - is_nothrow_constructible_v, _Closure> && - is_nothrow_constructible_v, _OtherClosure>) { - return __range_adaptor_closure_t(std::__compose(std::forward<_OtherClosure>(__c2), std::forward<_Closure>(__c1))); - } +concept _RangeAdaptorClosure = !ranges::range> && requires { + // Ensure that `remove_cvref_t<_Tp>` is derived from `__range_adaptor_closure>` and isn't derived + // from `__range_adaptor_closure` for any other type `U`. + { ranges::__derived_from_range_adaptor_closure((remove_cvref_t<_Tp>*)nullptr) } -> same_as>; }; +template + requires invocable<_Closure, _Range> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) +operator|(_Range&& __range, _Closure&& __closure) noexcept(is_nothrow_invocable_v<_Closure, _Range>) { + return std::invoke(std::forward<_Closure>(__closure), std::forward<_Range>(__range)); +} + +template <_RangeAdaptorClosure _Closure, _RangeAdaptorClosure _OtherClosure> + requires constructible_from, _Closure> && constructible_from, _OtherClosure> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator|(_Closure&& __c1, _OtherClosure&& __c2) noexcept( + is_nothrow_constructible_v, _Closure> && + is_nothrow_constructible_v, _OtherClosure>) { + return __range_adaptor_closure_t(std::__compose(std::forward<_OtherClosure>(__c2), std::forward<_Closure>(__c1))); +} + +template + requires is_class_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> +struct __range_adaptor_closure {}; + +# if _LIBCPP_STD_VER >= 23 +template + requires is_class_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> +class range_adaptor_closure : public __range_adaptor_closure<_Tp> {}; +# endif // _LIBCPP_STD_VER >= 23 + +} // namespace ranges + #endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/repeat_view.h b/libcxx/include/__ranges/repeat_view.h index 5caea757a393141263f95ba0ecdf56cbd657ca26..0941770f0eef80f82dcb46bbb1e70b97d3b96825 100644 --- a/libcxx/include/__ranges/repeat_view.h +++ b/libcxx/include/__ranges/repeat_view.h @@ -229,13 +229,13 @@ namespace views { namespace __repeat { struct __fn { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) -> decltype( ranges::repeat_view(std::forward<_Tp>(__value))) { return ranges::repeat_view(std::forward<_Tp>(__value)); } template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h index 98f17be04f628f5d78bf1b86c3798fdce52eba6d..ce3606aedfefb93cf4606035a5c5368c7173bda5 100644 --- a/libcxx/include/__ranges/split_view.h +++ b/libcxx/include/__ranges/split_view.h @@ -200,7 +200,7 @@ namespace __split_view { struct __fn { // clang-format off template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const noexcept(noexcept(split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) -> decltype( split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) @@ -209,7 +209,7 @@ struct __fn { template requires constructible_from, _Pattern> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const noexcept(is_nothrow_constructible_v, _Pattern>) { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); } diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h index 83ed5ca0ebd390960ff574e715474b4a4ea7525a..27ca8155a69b18831284230f5ede4dd8e3eed722 100644 --- a/libcxx/include/__ranges/take_view.h +++ b/libcxx/include/__ranges/take_view.h @@ -308,7 +308,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires(__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept(views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) -> decltype( views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { return views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } @@ -319,7 +319,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires(__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept(views::repeat(*__range.__value_, static_cast<_Dist>(__n)))) -> decltype( views::repeat(*__range.__value_, static_cast<_Dist>(__n))) { return views::repeat(*__range.__value_, static_cast<_Dist>(__n)); } diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h index 67818c521b150006f48b8223c9507da6f3106156..8a815bce58111e80a67a410b9a32c0e0c19e2485 100644 --- a/libcxx/include/__ranges/to.h +++ b/libcxx/include/__ranges/to.h @@ -85,7 +85,7 @@ concept __always_false = false; // `ranges::to` base template -- the `_Container` type is a simple type template parameter. template requires(!view<_Container>) -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Container to(_Range&& __range, _Args&&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Container to(_Range&& __range, _Args&&... __args) { // Mandates: C is a cv-unqualified class type. static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const"); static_assert( @@ -192,7 +192,7 @@ struct _Deducer { // `ranges::to` specialization -- `_Container` is a template template parameter requiring deduction to figure out the // container element type. template