diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index 2e503c867403bcf6fc56f6eed024229b82a0cc1d..81e9246de9b5895d1ab099a6b8a9919f2f569416 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -108,7 +108,7 @@ function add-dependencies() { compiler-rt|libc|openmp) echo clang lld ;; - flang|lldb) + flang|lldb|libclc) for p in llvm clang; do echo $p done diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c4727a0c267d3ecb5a3a5495945ce417d5adc38a..37aea5f6657f01f9b3da1a81bedf3103ad8bddd1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -113,11 +113,11 @@ clang/test/AST/Interp/ @tbaederr # MLIR NVVM Dialect in MLIR /mlir/**/LLVMIR/**/BasicPtxBuilderInterface* @grypp -/mlir/**/NVVM*/ @grypp +/mlir/**/NVVM* @grypp # MLIR Python Bindings -/mlir/test/python/ @makslevental @stellaraccident -/mlir/python/ @makslevental @stellaraccident +/mlir/test/python/ @ftynse @makslevental @stellaraccident +/mlir/python/ @ftynse @makslevental @stellaraccident # BOLT /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml index a0428336d300f9ac3d4eaff2f2daf4100e4ccdfc..9cf64417d3cb2cce3a61707ae1693e692c6e1a0e 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -1,3 +1,9 @@ +ClangIR: + - clang/include/clang/CIR/**/* + - clang/lib/CIR/**/* + - clang/tools/cir-*/**/* + - clang/test/CIR/**/* + clang:dataflow: - clang/include/clang/Analysis/FlowSensitive/**/* - clang/lib/Analysis/FlowSensitive/**/* @@ -938,3 +944,6 @@ openmp:libomptarget: bazel: - utils/bazel/** + +offload: + - offload/** diff --git a/clang-tools-extra/clang-tidy/add_new_check.py b/clang-tools-extra/clang-tidy/add_new_check.py index a6af76809af02a2c7e6e46187208138148e8f00f..3b14d5d158d2d0a5e800075b6e96289e6e07ce5a 100755 --- a/clang-tools-extra/clang-tidy/add_new_check.py +++ b/clang-tools-extra/clang-tidy/add_new_check.py @@ -211,7 +211,7 @@ def adapt_module(module_path, module, check_name, check_name_camel): f.write(check_decl) else: match = re.search( - 'registerCheck<(.*)> *\( *(?:"([^"]*)")?', line + r'registerCheck<(.*)> *\( *(?:"([^"]*)")?', line ) prev_line = None if match: @@ -383,7 +383,7 @@ def update_checks_list(clang_tidy_path): if stmt_start_pos == -1: return "" stmt = code[stmt_start_pos + 1 : stmt_end_pos] - matches = re.search('registerCheck<([^>:]*)>\(\s*"([^"]*)"\s*\)', stmt) + matches = re.search(r'registerCheck<([^>:]*)>\(\s*"([^"]*)"\s*\)', stmt) if matches and matches[2] == full_check_name: class_name = matches[1] if "::" in class_name: @@ -401,8 +401,8 @@ def update_checks_list(clang_tidy_path): # Examine code looking for a c'tor definition to get the base class name. def get_base_class(code, check_file): check_class_name = os.path.splitext(os.path.basename(check_file))[0] - ctor_pattern = check_class_name + "\([^:]*\)\s*:\s*([A-Z][A-Za-z0-9]*Check)\(" - matches = re.search("\s+" + check_class_name + "::" + ctor_pattern, code) + ctor_pattern = check_class_name + r"\([^:]*\)\s*:\s*([A-Z][A-Za-z0-9]*Check)\(" + matches = re.search(r"\s+" + check_class_name + "::" + ctor_pattern, code) # The constructor might be inline in the header. if not matches: @@ -476,7 +476,7 @@ def update_checks_list(clang_tidy_path): # Orphan page, don't list it. return "", "" - match = re.search(".*:http-equiv=refresh: \d+;URL=(.*).html(.*)", content) + match = re.search(r".*:http-equiv=refresh: \d+;URL=(.*).html(.*)", content) # Is it a redirect? return check_name, match @@ -505,7 +505,7 @@ def update_checks_list(clang_tidy_path): ref_begin = "" ref_end = "_" else: - redirect_parts = re.search("^\.\./([^/]*)/([^/]*)$", match.group(1)) + redirect_parts = re.search(r"^\.\./([^/]*)/([^/]*)$", match.group(1)) title = redirect_parts[1] + "-" + redirect_parts[2] target = redirect_parts[1] + "/" + redirect_parts[2] autofix = has_auto_fix(title) diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index c608fe713f9f5b8d9f34dcff8b26e2655da595a2..e7be8134781e48de409fcd36a0e7d9dfe10a06d1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -72,7 +72,7 @@ void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) { DeclarationMatcher FindOverload = cxxConstructorDecl( - hasParameter(0, ForwardingRefParm), + hasParameter(0, ForwardingRefParm), unless(isDeleted()), unless(hasAnyParameter( // No warning: enable_if as constructor parameter. parmVarDecl(hasType(isEnableIf())))), diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index 855c4a2efc373edeac6c01f48fb2e527e6231a87..9c3c7cc70c187b2e0bb43f1e18280492b79e91ab 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -444,7 +444,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer( if (!F->hasInClassInitializer() && utils::type_traits::isTriviallyDefaultConstructible(F->getType(), Context) && - !isEmpty(Context, F->getType()) && !F->isUnnamedBitfield() && + !isEmpty(Context, F->getType()) && !F->isUnnamedBitField() && !AnyMemberHasInitPerUnion) FieldsToInit.insert(F); }); diff --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp index 5134eb51a03226caa33aa14f6c195d9e2c2375b0..93151024064b42a72cc478d125e558d0e0eb3572 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp @@ -26,7 +26,7 @@ getAllNamedFields(const CXXRecordDecl *Record) { std::set Result; for (const auto *Field : Record->fields()) { // Static data members are not in this range. - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; Result.insert(Field); } diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp index 1dde0490517852d91cd427790371c222c1a9f779..4a9426ee7e8bbbe35f46cfbc1a9670833aab123d 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp @@ -99,7 +99,7 @@ ExceptionSpecAnalyzer::analyzeRecord(const CXXRecordDecl *RecordDecl, } for (const auto *FDecl : RecordDecl->fields()) - if (!FDecl->isInvalidDecl() && !FDecl->isUnnamedBitfield()) { + if (!FDecl->isInvalidDecl() && !FDecl->isUnnamedBitField()) { State Result = analyzeFieldDecl(FDecl, Kind); if (Result == State::Throwing || Result == State::Unknown) return Result; diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 5790273d625ef14f7ae06ff608b88cd65926e808..1c4c2a79b5c05103cef3b9273f63dec556b9a584 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -30,6 +30,7 @@ #include "refactor/Rename.h" #include "refactor/Tweak.h" #include "support/Cancellation.h" +#include "support/Context.h" #include "support/Logger.h" #include "support/MemoryTree.h" #include "support/ThreadsafeFS.h" @@ -112,7 +113,12 @@ struct UpdateIndexCallbacks : public ParsingCallbacks { // Index outlives TUScheduler (declared first) FIndex(FIndex), // shared_ptr extends lifetime - Stdlib(Stdlib)]() mutable { + Stdlib(Stdlib), + // We have some FS implementations that rely on information in + // the context. + Ctx(Context::current().clone())]() mutable { + // Make sure we install the context into current thread. + WithContext C(std::move(Ctx)); clang::noteBottomOfStack(); IndexFileIn IF; IF.Symbols = indexStandardLibrary(std::move(CI), Loc, *TFS); diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp index f181c7befec156a9afba0548da585ecc55010c9a..d5818e0ca309b03fafadc20f1fbdfe4f902ab615 100644 --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -700,6 +700,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI, Result->Marks = CapturedInfo.takeMarks(); Result->StatCache = StatCache; Result->MainIsIncludeGuarded = CapturedInfo.isMainFileIncludeGuarded(); + Result->TargetOpts = CI.TargetOpts; if (PreambleCallback) { trace::Span Tracer("Running PreambleCallback"); auto Ctx = CapturedInfo.takeLife(); @@ -913,6 +914,12 @@ PreamblePatch PreamblePatch::createMacroPatch(llvm::StringRef FileName, } void PreamblePatch::apply(CompilerInvocation &CI) const { + // Make sure the compilation uses same target opts as the preamble. Clang has + // no guarantees around using arbitrary options when reusing PCHs, and + // different target opts can result in crashes, see + // ParsedASTTest.PreambleWithDifferentTarget. + CI.TargetOpts = Baseline->TargetOpts; + // No need to map an empty file. if (PatchContents.empty()) return; diff --git a/clang-tools-extra/clangd/Preamble.h b/clang-tools-extra/clangd/Preamble.h index 37da3833748a9c6e1357bdba3cbf509b31686414..160b884beb56bb78f1b0e79d435a6c352e90e73a 100644 --- a/clang-tools-extra/clangd/Preamble.h +++ b/clang-tools-extra/clangd/Preamble.h @@ -30,6 +30,7 @@ #include "clang-include-cleaner/Record.h" #include "support/Path.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetOptions.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PrecompiledPreamble.h" #include "clang/Lex/Lexer.h" @@ -97,6 +98,10 @@ struct PreambleData { // Version of the ParseInputs this preamble was built from. std::string Version; tooling::CompileCommand CompileCommand; + // Target options used when building the preamble. Changes in target can cause + // crashes when deserializing preamble, this enables consumers to use the + // same target (without reparsing CompileCommand). + std::shared_ptr TargetOpts = nullptr; PrecompiledPreamble Preamble; std::vector Diags; // Processes like code completions and go-to-definitions will need #include diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index e432db8d0912e736743149943c39672998f7f7ed..7f1ae5c43d80c69cd896c886cdd4100467e9b88c 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS support AllTargetsInfos FrontendOpenMP + TargetParser ) if(CLANG_BUILT_STANDALONE) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 8fbac73cb653bcc20d4b68a92a6e80f2bd881315..96d1ee1f0add7359e30dc7435d76d4e8c295cb7e 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -4160,7 +4160,32 @@ TEST(CompletionTest, DoNotCrash) { auto Completions = completions(Case); } } +TEST(CompletionTest, PreambleFromDifferentTarget) { + constexpr std::string_view PreambleTarget = "x86_64"; + constexpr std::string_view Contents = + "int foo(int); int num; int num2 = foo(n^"; + Annotations Test(Contents); + auto TU = TestTU::withCode(Test.code()); + TU.ExtraArgs.emplace_back("-target"); + TU.ExtraArgs.emplace_back(PreambleTarget); + auto Preamble = TU.preamble(); + ASSERT_TRUE(Preamble); + // Switch target to wasm. + TU.ExtraArgs.pop_back(); + TU.ExtraArgs.emplace_back("wasm32"); + + MockFS FS; + auto Inputs = TU.inputs(FS); + auto Result = codeComplete(testPath(TU.Filename), Test.point(), + Preamble.get(), Inputs, {}); + auto Signatures = + signatureHelp(testPath(TU.Filename), Test.point(), *Preamble, Inputs, {}); + + // Make sure we don't crash. + EXPECT_THAT(Result.Completions, Not(testing::IsEmpty())); + EXPECT_THAT(Signatures.signatures, Not(testing::IsEmpty())); +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp index 500b72b9b327a04fad77afdf27697decdda408ba..4bb76cd6ab8304af8586316441c3cd06fd5bbc7d 100644 --- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp @@ -12,10 +12,7 @@ //===----------------------------------------------------------------------===// #include "../../clang-tidy/ClangTidyCheck.h" -#include "../../clang-tidy/ClangTidyModule.h" -#include "../../clang-tidy/ClangTidyModuleRegistry.h" #include "AST.h" -#include "CompileCommands.h" #include "Compiler.h" #include "Config.h" #include "Diagnostics.h" @@ -32,7 +29,6 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Lex/PPCallbacks.h" #include "clang/Tooling/Syntax/Tokens.h" #include "llvm/ADT/StringRef.h" #include "llvm/Testing/Annotations/Annotations.h" @@ -41,6 +37,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include +#include #include #include @@ -347,9 +344,8 @@ TEST(ParsedASTTest, CollectsMainFileMacroExpansions) { } for (const auto &R : AST.getMacros().UnknownMacros) MacroExpansionPositions.push_back(R.StartOffset); - EXPECT_THAT( - MacroExpansionPositions, - testing::UnorderedElementsAreArray(TestCase.points())); + EXPECT_THAT(MacroExpansionPositions, + testing::UnorderedElementsAreArray(TestCase.points())); } MATCHER_P(withFileName, Inc, "") { return arg.FileName == Inc; } @@ -768,6 +764,35 @@ main: << "Should not try to build AST for assembly source file"; } +TEST(ParsedASTTest, PreambleWithDifferentTarget) { + constexpr std::string_view kPreambleTarget = "x86_64"; + // Specifically picking __builtin_va_list as it triggers crashes when + // switching to wasm. + // It's due to different predefined types in different targets. + auto TU = TestTU::withHeaderCode("void foo(__builtin_va_list);"); + TU.Code = "void bar() { foo(2); }"; + TU.ExtraArgs.emplace_back("-target"); + TU.ExtraArgs.emplace_back(kPreambleTarget); + const auto Preamble = TU.preamble(); + + // Switch target to wasm. + TU.ExtraArgs.pop_back(); + TU.ExtraArgs.emplace_back("wasm32"); + + IgnoreDiagnostics Diags; + MockFS FS; + auto Inputs = TU.inputs(FS); + auto CI = buildCompilerInvocation(Inputs, Diags); + ASSERT_TRUE(CI) << "Failed to build compiler invocation"; + + auto AST = ParsedAST::build(testPath(TU.Filename), std::move(Inputs), + std::move(CI), {}, Preamble); + + ASSERT_TRUE(AST); + // We use the target from preamble, not with the most-recent flags. + EXPECT_EQ(AST->getASTContext().getTargetInfo().getTriple().getArchName(), + llvm::StringRef(kPreambleTarget)); +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 7095c564444fe68e4845185ec4f977b8cea89d84..a457e6fcae946256ee907b33a206542f29f1c055 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -147,6 +147,10 @@ Changes in existing checks ` check by detecting side effect from calling a method with non-const reference parameters. +- Improved :doc:`bugprone-forwarding-reference-overload + ` + check to ignore deleted constructors which won't hide other overloads. + - Improved :doc:`bugprone-inc-dec-in-conditions ` check to ignore code within unevaluated contexts, such as ``decltype``. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp index 38b0691bc9f1ecb8de9ddcc1f5fd1654d44739e1..92dfb718bb51b7bda177f254233b28856755e198 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp @@ -251,3 +251,13 @@ public: Test10(T &&Item, E e) : e(e){} }; + +// A deleted ctor cannot hide anything +class Test11 { +public: + template + Test11(T&&) = delete; + + Test11(const Test11 &) = default; + Test11(Test11 &&) = default; +}; diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index 393d97a4cf1a3302db9be62d1982d0f485d52a3b..30a3b9116a461f3f65d2bfdfab0f5aaecccc2e6c 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -65,7 +65,6 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH LLDB_EMBED_PYTHON_HOME LLDB_PYTHON_HOME LLDB_PYTHON_RELATIVE_PATH - LLDB_TEST_USE_VENDOR_PACKAGES LLDB_TEST_USER_ARGS Python3_EXECUTABLE Python3_LIBRARIES diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 96ad92b540b47f86f2ac31b4c0b9f97eb9f20270..193bbd6b1a4702c879f8a07ee331210ca20506c3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -287,6 +287,9 @@ Attribute Changes in Clang This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to apply to this class. +- Clang now warns that the ``exclude_from_explicit_instantiation`` attribute + is ignored when applied to a local class or a member thereof. + Improvements to Clang's diagnostics ----------------------------------- - Clang now applies syntax highlighting to the code snippets it @@ -364,6 +367,8 @@ Improvements to Clang's diagnostics - Clang now uses the correct type-parameter-key (``class`` or ``typename``) when printing template template parameter declarations. +- Clang now diagnoses requires expressions with explicit object parameters. + Improvements to Clang's time-trace ---------------------------------- @@ -422,6 +427,14 @@ Bug Fixes in This Version - Fixed an assertion failure on invalid InitListExpr in C89 mode (#GH88008). +- Clang will no longer diagnose an erroneous non-dependent ``switch`` condition + during instantiation, and instead will only diagnose it once, during checking + of the function template. + +- Clang now allows the value of unroll count to be zero in ``#pragma GCC unroll`` and ``#pragma unroll``. + The values of 0 and 1 block any unrolling of the loop. This keeps the same behavior with GCC. + Fixes (`#88624 `_). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -534,6 +547,8 @@ Bug Fixes to C++ Support Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399). - Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329). - 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). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst index 8d5529d5d37db59c7dfff65f3bc7ff0c49388ad6..ee57fb5da6485769213f8485ac0e7a7f9fbd774d 100644 --- a/clang/docs/StandardCPlusPlusModules.rst +++ b/clang/docs/StandardCPlusPlusModules.rst @@ -483,6 +483,13 @@ violations with the flag enabled. ABI Impacts ----------- +This section describes the new ABI changes brought by modules. + +Only Itanium C++ ABI related change are mentioned + +Mangling Names +~~~~~~~~~~~~~~ + The declarations in a module unit which are not in the global module fragment have new linkage names. For example, @@ -520,6 +527,23 @@ is attached to the global module fragments. For example: Now the linkage name of ``NS::foo()`` will be ``_ZN2NS3fooEv``. +Module Initializers +~~~~~~~~~~~~~~~~~~~ + +All the importable module units are required to emit an initializer function. +The initializer function should contain calls to importing modules first and +all the dynamic-initializers in the current module unit then. + +Translation units explicitly or implicitly importing named modules must call +the initializer functions of the imported named modules within the sequence of +the dynamic-initializers in the TU. Initializations of entities at namespace +scope are appearance-ordered. This (recursively) extends into imported modules +at the point of appearance of the import declaration. + +It is allowed to omit calls to importing modules if it is known empty. + +It is allowed to omit calls to importing modules for which is known to be called. + Reduced BMI ----------- diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h index 8879f9f3229ff3f755162bf9cbd200df07e2d641..2c4ec2ce67f36bb3b705b99dd257230a3adcd60b 100644 --- a/clang/include/clang/AST/ASTMutationListener.h +++ b/clang/include/clang/AST/ASTMutationListener.h @@ -27,6 +27,7 @@ namespace clang { class FunctionTemplateDecl; class Module; class NamedDecl; + class NamespaceDecl; class ObjCCategoryDecl; class ObjCContainerDecl; class ObjCInterfaceDecl; @@ -35,6 +36,7 @@ namespace clang { class QualType; class RecordDecl; class TagDecl; + class TranslationUnitDecl; class ValueDecl; class VarDecl; class VarTemplateDecl; @@ -147,6 +149,31 @@ public: virtual void AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) {} + /// The parser find the named module declaration. + virtual void EnteringModulePurview() {} + + /// An mangling number was added to a Decl + /// + /// \param D The decl that got a mangling number + /// + /// \param Number The mangling number that was added to the Decl + virtual void AddedManglingNumber(const Decl *D, unsigned Number) {} + + /// An static local number was added to a Decl + /// + /// \param D The decl that got a static local number + /// + /// \param Number The static local number that was added to the Decl + virtual void AddedStaticLocalNumbers(const Decl *D, unsigned Number) {} + + /// An anonymous namespace was added the translation unit decl + /// + /// \param TU The translation unit decl that got a new anonymous namespace + /// + /// \param AnonNamespace The anonymous namespace that was added + virtual void AddedAnonymousNamespace(const TranslationUnitDecl *TU, + NamespaceDecl *AnonNamespace) {} + // NOTE: If new methods are added they should also be added to // MultiplexASTMutationListener. }; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 01af50ca694fdd8611bd3bb08573d9fe1622d6b7..8b121896d66d158d06be1c317d7d1e1698782bc5 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -120,7 +120,7 @@ public: ASTContext &getASTContext() const { return Ctx; } NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } - void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; } + void setAnonymousNamespace(NamespaceDecl *D); static TranslationUnitDecl *Create(ASTContext &C); @@ -157,7 +157,7 @@ public: SourceLocation CommentLoc, PragmaMSCommentKind CommentKind, StringRef Arg); - static PragmaCommentDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static PragmaCommentDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned ArgSize); PragmaMSCommentKind getCommentKind() const { return CommentKind; } @@ -192,7 +192,7 @@ public: SourceLocation Loc, StringRef Name, StringRef Value); static PragmaDetectMismatchDecl * - CreateDeserialized(ASTContext &C, unsigned ID, unsigned NameValueSize); + CreateDeserialized(ASTContext &C, DeclID ID, unsigned NameValueSize); StringRef getName() const { return getTrailingObjects(); } StringRef getValue() const { return getTrailingObjects() + ValueStart; } @@ -518,7 +518,7 @@ public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, SourceLocation GnuLabelL); - static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static LabelDecl *CreateDeserialized(ASTContext &C, DeclID ID); LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } @@ -581,7 +581,7 @@ public: IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested); - static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static NamespaceDecl *CreateDeserialized(ASTContext &C, DeclID ID); using redecl_range = redeclarable_base::redecl_range; using redecl_iterator = redeclarable_base::redecl_iterator; @@ -1146,7 +1146,7 @@ public: const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S); - static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static VarDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -1728,7 +1728,7 @@ public: static ImplicitParamDecl *Create(ASTContext &C, QualType T, ImplicitParamKind ParamKind); - static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ImplicitParamDecl *CreateDeserialized(ASTContext &C, DeclID ID); ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType Type, @@ -1782,7 +1782,7 @@ public: TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg); - static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ParmVarDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -2178,7 +2178,7 @@ public: bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause); - static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static FunctionDecl *CreateDeserialized(ASTContext &C, DeclID ID); DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); @@ -3136,7 +3136,7 @@ public: TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle); - static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static FieldDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Returns the index of this field within its record, /// as appropriate for passing to ASTRecordLayout::getFieldOffset. @@ -3149,7 +3149,7 @@ public: bool isBitField() const { return BitField; } /// Determines whether this is an unnamed bitfield. - bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); } + bool isUnnamedBitField() const { return isBitField() && !getDeclName(); } /// Determines whether this field is a /// representative for an anonymous struct or union. Such fields are @@ -3311,7 +3311,7 @@ public: SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V); - static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static EnumConstantDecl *CreateDeserialized(ASTContext &C, DeclID ID); const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } @@ -3357,7 +3357,7 @@ public: QualType T, llvm::MutableArrayRef CH); - static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static IndirectFieldDecl *CreateDeserialized(ASTContext &C, DeclID ID); using chain_iterator = ArrayRef::const_iterator; @@ -3542,7 +3542,7 @@ public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo); - static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static TypedefDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -3567,7 +3567,7 @@ public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo); - static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static TypeAliasDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -3977,7 +3977,7 @@ public: IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed); - static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static EnumDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Overrides to provide correct range when there's an enum-base specifier /// with forward declarations. @@ -4182,7 +4182,7 @@ public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr); - static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); + static RecordDecl *CreateDeserialized(const ASTContext &C, DeclID ID); RecordDecl *getPreviousDecl() { return cast_or_null( @@ -4433,7 +4433,7 @@ public: StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc); - static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceLocation getAsmLoc() const { return getLocation(); } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -4469,7 +4469,7 @@ class TopLevelStmtDecl : public Decl, public DeclContext { public: static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement); - static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; Stmt *getStmt() { return Statement; } @@ -4563,7 +4563,7 @@ protected: public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); - static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static BlockDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceLocation getCaretLocation() const { return getLocation(); } @@ -4717,7 +4717,7 @@ public: static CapturedDecl *Create(ASTContext &C, DeclContext *DC, unsigned NumParams); - static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static CapturedDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned NumParams); Stmt *getBody() const override; @@ -4851,7 +4851,7 @@ public: SourceLocation EndLoc); /// Create a new, deserialized module import declaration. - static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static ImportDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned NumLocations); /// Retrieve the module that was imported by the import declaration. @@ -4892,7 +4892,7 @@ private: public: static ExportDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation ExportLoc); - static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ExportDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceLocation getExportLoc() const { return getLocation(); } SourceLocation getRBraceLoc() const { return RBraceLoc; } @@ -4931,7 +4931,7 @@ class EmptyDecl : public Decl { public: static EmptyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); - static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static EmptyDecl *CreateDeserialized(ASTContext &C, DeclID ID); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Empty; } @@ -4957,7 +4957,7 @@ public: bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace); - static HLSLBufferDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static HLSLBufferDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getLocStart(), RBraceLoc); diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 1079993f4969456f87d9ba2e2e80fff8b0efa016..161e14fc896922fbacbd018df904a70b8c0b793b 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -349,6 +349,8 @@ 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 @@ -358,7 +360,7 @@ protected: /// \param Ctx The context in which we will allocate memory. /// \param ID The global ID of the deserialized declaration. /// \param Extra The amount of extra space to allocate after the object. - void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID, + void *operator new(std::size_t Size, const ASTContext &Ctx, DeclID ID, std::size_t Extra = 0); /// Allocate memory for a non-deserialized declaration. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 7aed4d5cbc002e2c60d743922f16d507bfb2a2dd..a7644d2a19d2459c0a746a62cb1fc06f5fa5c2d5 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -120,7 +120,7 @@ public: return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); } - static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static AccessSpecDecl *CreateDeserialized(ASTContext &C, DeclID ID); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -579,7 +579,7 @@ public: TypeSourceInfo *Info, SourceLocation Loc, unsigned DependencyKind, bool IsGeneric, LambdaCaptureDefault CaptureDefault); - static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); + static CXXRecordDecl *CreateDeserialized(const ASTContext &C, DeclID ID); bool isDynamicClass() const { return data().Polymorphic || data().NumVBases != 0; @@ -1980,7 +1980,7 @@ public: CXXConstructorDecl *Ctor = nullptr, DeductionCandidate Kind = DeductionCandidate::Normal); - static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, DeclID ID); ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; } const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; } @@ -2035,7 +2035,7 @@ public: static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc); - static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, DeclID ID); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2078,7 +2078,7 @@ public: ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); - static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static CXXMethodDecl *CreateDeserialized(ASTContext &C, DeclID ID); bool isStatic() const; bool isInstance() const { return !isStatic(); } @@ -2579,7 +2579,7 @@ public: friend class ASTDeclWriter; friend TrailingObjects; - static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static CXXConstructorDecl *CreateDeserialized(ASTContext &C, DeclID ID, uint64_t AllocKind); static CXXConstructorDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, @@ -2822,7 +2822,7 @@ public: bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause = nullptr); - static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); + static CXXDestructorDecl *CreateDeserialized(ASTContext & C, DeclID ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2881,7 +2881,7 @@ public: bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); - static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static CXXConversionDecl *CreateDeserialized(ASTContext &C, DeclID ID); ExplicitSpecifier getExplicitSpecifier() { return getCanonicalDecl()->ExplicitSpec; @@ -2948,7 +2948,7 @@ public: SourceLocation ExternLoc, SourceLocation LangLoc, LinkageSpecLanguageIDs Lang, bool HasBraces); - static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static LinkageSpecDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Return the language specified by this linkage specification. LinkageSpecLanguageIDs getLanguage() const { @@ -3096,7 +3096,7 @@ public: SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor); - static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(UsingLoc, getLocation()); @@ -3157,7 +3157,7 @@ public: SourceLocation IdentLoc, NamedDecl *Namespace); - static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, DeclID ID); using redecl_range = redeclarable_base::redecl_range; using redecl_iterator = redeclarable_base::redecl_iterator; @@ -3254,7 +3254,7 @@ public: LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling); } static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C, - unsigned ID) { + DeclID ID) { return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{}); } @@ -3357,7 +3357,7 @@ public: UsingShadowDecl(UsingShadow, C, DC, Loc, Name, Introducer, Target); } - static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static UsingShadowDecl *CreateDeserialized(ASTContext &C, DeclID ID); using redecl_range = redeclarable_base::redecl_range; using redecl_iterator = redeclarable_base::redecl_iterator; @@ -3566,7 +3566,7 @@ public: const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword); - static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static UsingDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -3645,7 +3645,7 @@ public: UsingDecl *Using, NamedDecl *Target, bool IsVirtual); static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); /// Override the UsingShadowDecl's getIntroducer, returning the UsingDecl that /// introduced this. @@ -3757,7 +3757,7 @@ public: SourceLocation UsingL, SourceLocation EnumL, SourceLocation NameL, TypeSourceInfo *EnumType); - static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static UsingEnumDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -3830,7 +3830,7 @@ public: NamedDecl *InstantiatedFrom, ArrayRef UsingDecls); - static UsingPackDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static UsingPackDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned NumExpansions); SourceRange getSourceRange() const override LLVM_READONLY { @@ -3924,7 +3924,7 @@ public: const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc); static UnresolvedUsingValueDecl * - CreateDeserialized(ASTContext &C, unsigned ID); + CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -4015,7 +4015,7 @@ public: SourceLocation EllipsisLoc); static UnresolvedUsingTypenameDecl * - CreateDeserialized(ASTContext &C, unsigned ID); + CreateDeserialized(ASTContext &C, DeclID ID); /// Retrieves the canonical declaration of this declaration. UnresolvedUsingTypenameDecl *getCanonicalDecl() override { @@ -4045,7 +4045,7 @@ public: SourceLocation Loc, DeclarationName Name); static UnresolvedUsingIfExistsDecl *CreateDeserialized(ASTContext &Ctx, - unsigned ID); + DeclID ID); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingIfExists; } @@ -4073,7 +4073,7 @@ public: SourceLocation StaticAssertLoc, Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, bool Failed); - static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static StaticAssertDecl *CreateDeserialized(ASTContext &C, DeclID ID); Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } @@ -4120,7 +4120,7 @@ public: static BindingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id); - static BindingDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static BindingDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Get the expression to which this declaration is bound. This may be null /// in two different cases: while parsing the initializer for the @@ -4189,7 +4189,7 @@ public: QualType T, TypeSourceInfo *TInfo, StorageClass S, ArrayRef Bindings); - static DecompositionDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static DecompositionDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned NumBindings); ArrayRef bindings() const { @@ -4246,7 +4246,7 @@ public: SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, SourceLocation StartL, IdentifierInfo *Getter, IdentifierInfo *Setter); - static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static MSPropertyDecl *CreateDeserialized(ASTContext &C, DeclID ID); static bool classof(const Decl *D) { return D->getKind() == MSProperty; } @@ -4300,7 +4300,7 @@ private: MSGuidDecl(DeclContext *DC, QualType T, Parts P); static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P); - static MSGuidDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static MSGuidDecl *CreateDeserialized(ASTContext &C, DeclID ID); // Only ASTContext::getMSGuidDecl and deserialization create these. friend class ASTContext; @@ -4353,7 +4353,7 @@ class UnnamedGlobalConstantDecl : public ValueDecl, static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T, const APValue &APVal); static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); // Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create // these. diff --git a/clang/include/clang/AST/DeclFriend.h b/clang/include/clang/AST/DeclFriend.h index 3e6ca5b3219259e1eafb908afc08208ec5bfc251..b56627a5337d63a80af5b4ad2856aad5c1be2998 100644 --- a/clang/include/clang/AST/DeclFriend.h +++ b/clang/include/clang/AST/DeclFriend.h @@ -112,7 +112,7 @@ public: Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, SourceLocation FriendL, ArrayRef FriendTypeTPLists = std::nullopt); - static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static FriendDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned FriendTypeNumTPLists); /// If this friend declaration names an (untemplated but possibly diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index b8d17dd06d1550082446496c9d02ef5fa9c759a5..7780afa6f1cf5c11b286b39613cc18c21293630b 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -236,7 +236,7 @@ public: ObjCImplementationControl impControl = ObjCImplementationControl::None, bool HasRelatedResultType = false); - static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCMethodDecl *CreateDeserialized(ASTContext &C, DeclID ID); ObjCMethodDecl *getCanonicalDecl() override; const ObjCMethodDecl *getCanonicalDecl() const { @@ -614,7 +614,7 @@ public: IdentifierInfo *name, SourceLocation colonLoc, TypeSourceInfo *boundInfo); - static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID); + static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -789,7 +789,7 @@ public: TypeSourceInfo *TSI, PropertyControl propControl = None); - static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } @@ -1279,7 +1279,7 @@ public: ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc = SourceLocation(), bool isInternal = false); - static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID); + static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, DeclID ID); /// Retrieve the type parameters of this class. /// @@ -1969,7 +1969,7 @@ public: TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = nullptr, bool synthesized = false); - static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCIvarDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Return the class interface that this ivar is logically contained /// in; this is either the interface where the ivar was declared, or the @@ -2039,7 +2039,7 @@ public: SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW); - static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, DeclID ID); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2142,7 +2142,7 @@ public: SourceLocation atStartLoc, ObjCProtocolDecl *PrevDecl); - static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, DeclID ID); const ObjCProtocolList &getReferencedProtocols() const { assert(hasDefinition() && "No definition available!"); @@ -2361,7 +2361,7 @@ public: ObjCTypeParamList *typeParamList, SourceLocation IvarLBraceLoc = SourceLocation(), SourceLocation IvarRBraceLoc = SourceLocation()); - static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, DeclID ID); ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } @@ -2558,7 +2558,7 @@ public: Create(ASTContext &C, DeclContext *DC, const IdentifierInfo *Id, ObjCInterfaceDecl *classInterface, SourceLocation nameLoc, SourceLocation atStartLoc, SourceLocation CategoryNameLoc); - static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, DeclID ID); ObjCCategoryDecl *getCategoryDecl() const; @@ -2640,7 +2640,7 @@ public: SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()); - static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// init_iterator - Iterates through the ivar initializer list. using init_iterator = CXXCtorInitializer **; @@ -2780,7 +2780,7 @@ public: ObjCInterfaceDecl* aliasedClass); static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } @@ -2851,7 +2851,7 @@ public: ObjCIvarDecl *ivarDecl, SourceLocation ivarLoc); - static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; diff --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h index 8fdfddb6c1fd74bf2ddc3b852b0e28679b286926..c7ede7f2157fef7676cb6bf068761c49602479d9 100644 --- a/clang/include/clang/AST/DeclOpenMP.h +++ b/clang/include/clang/AST/DeclOpenMP.h @@ -133,7 +133,7 @@ public: SourceLocation L, ArrayRef VL); static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, - unsigned ID, unsigned N); + DeclID ID, unsigned N); typedef MutableArrayRef::iterator varlist_iterator; typedef ArrayRef::iterator varlist_const_iterator; @@ -214,7 +214,7 @@ public: QualType T, OMPDeclareReductionDecl *PrevDeclInScope); /// Create deserialized declare reduction node. static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); /// Get combiner expression of the declare reduction construct. Expr *getCombiner() { return Combiner; } @@ -318,7 +318,7 @@ public: ArrayRef Clauses, OMPDeclareMapperDecl *PrevDeclInScope); /// Creates deserialized declare mapper node. - static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned N); using clauselist_iterator = MutableArrayRef::iterator; @@ -397,7 +397,7 @@ public: IdentifierInfo *Id, QualType T, SourceLocation StartLoc); - static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, DeclID ID); SourceRange getSourceRange() const override LLVM_READONLY; @@ -427,7 +427,7 @@ public: static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef CL); /// Create deserialized requires node. - static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static OMPRequiresDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned N); using clauselist_iterator = MutableArrayRef::iterator; @@ -495,7 +495,7 @@ public: static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef VL, ArrayRef CL); - static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID, + static OMPAllocateDecl *CreateDeserialized(ASTContext &C, DeclID ID, unsigned NVars, unsigned NClauses); typedef MutableArrayRef::iterator varlist_iterator; diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index f24e71ff229648d80336e76faef5abbe850a0fe9..e2afff8d445016d5dc656fb016c789b56e39add2 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1087,7 +1087,7 @@ public: NamedDecl *Decl); /// Create an empty function template node. - static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID); // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1204,9 +1204,9 @@ public: bool Typename, bool ParameterPack, bool HasTypeConstraint = false, std::optional NumExpanded = std::nullopt); static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, - unsigned ID); + DeclID ID); static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, - unsigned ID, + DeclID ID, bool HasTypeConstraint); /// Whether this template type parameter was declared with @@ -1414,10 +1414,10 @@ public: ArrayRef ExpandedTInfos); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID, + DeclID ID, bool HasTypeConstraint); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID, + DeclID ID, unsigned NumExpandedTypes, bool HasTypeConstraint); @@ -1632,9 +1632,9 @@ public: ArrayRef Expansions); static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID, + DeclID ID, unsigned NumExpansions); using TemplateParmPosition::getDepth; @@ -1858,7 +1858,7 @@ public: ArrayRef Args, ClassTemplateSpecializationDecl *PrevDecl); static ClassTemplateSpecializationDecl * - CreateDeserialized(ASTContext &C, unsigned ID); + CreateDeserialized(ASTContext &C, DeclID ID); void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const override; @@ -2110,7 +2110,7 @@ public: ClassTemplatePartialSpecializationDecl *PrevDecl); static ClassTemplatePartialSpecializationDecl * - CreateDeserialized(ASTContext &C, unsigned ID); + CreateDeserialized(ASTContext &C, DeclID ID); ClassTemplatePartialSpecializationDecl *getMostRecentDecl() { return cast( @@ -2306,7 +2306,7 @@ public: NamedDecl *Decl); /// Create an empty class template node. - static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ClassTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. @@ -2472,7 +2472,7 @@ public: MutableArrayRef Params, FriendUnion Friend, SourceLocation FriendLoc); - static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static FriendTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// If this friend declaration names a templated type (or /// a dependent member type of a templated type), return that @@ -2573,7 +2573,7 @@ public: NamedDecl *Decl); /// Create an empty alias template node. - static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID); // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2670,7 +2670,7 @@ public: TypeSourceInfo *TInfo, StorageClass S, ArrayRef Args); static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const override; @@ -2901,7 +2901,7 @@ public: const TemplateArgumentListInfo &ArgInfos); static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); VarTemplatePartialSpecializationDecl *getMostRecentDecl() { return cast( @@ -3078,7 +3078,7 @@ public: VarDecl *Decl); /// Create an empty variable template node. - static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static VarTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID); /// Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. @@ -3183,7 +3183,7 @@ public: SourceLocation L, DeclarationName Name, TemplateParameterList *Params, Expr *ConstraintExpr); - static ConceptDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ConceptDecl *CreateDeserialized(ASTContext &C, DeclID ID); Expr *getConstraintExpr() const { return ConstraintExpr; @@ -3232,7 +3232,7 @@ public: Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, ArrayRef ConvertedArgs); static ImplicitConceptSpecializationDecl * - CreateDeserialized(const ASTContext &C, unsigned ID, + CreateDeserialized(const ASTContext &C, DeclID ID, unsigned NumTemplateArgs); ArrayRef getTemplateArguments() const { @@ -3275,7 +3275,7 @@ private: static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T, const APValue &V); static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + DeclID ID); /// Only ASTContext::getTemplateParamObjectDecl and deserialization /// create these. diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 07587849eb12190a8a8a097bbb57cb4a9abedc2f..8b6d3221aa066bcc73b9a2781d614c26707e2f54 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -156,6 +156,56 @@ public: Expr *ConditionExpr, SourceLocation EndLoc); }; +/// Represents oen of a handful of classes that have a single integer +/// expression. +class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithParams { + Expr *IntExpr; + +protected: + OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *IntExpr, + SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), + IntExpr(IntExpr) {} + +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)); + } + + const_child_range children() const { + return const_child_range(reinterpret_cast(&IntExpr), + reinterpret_cast(&IntExpr + 1)); + } +}; + +class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr { + OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *IntExpr, SourceLocation EndLoc); + +public: + static OpenACCNumWorkersClause *Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + Expr *IntExpr, SourceLocation EndLoc); +}; + +class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr { + OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *IntExpr, SourceLocation EndLoc); + +public: + static OpenACCVectorLengthClause * + Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *IntExpr, SourceLocation EndLoc); +}; + template class OpenACCClauseVisitor { Impl &getDerived() { return static_cast(*this); } diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index 27ad32c1694f776de99691c204abea4bc6a1b0a3..f9fd3db1fb67fc78be3c6bfb3df55522dac68391 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -56,6 +56,7 @@ class RecordInitListHelper { public: // `InitList` must have record type. RecordInitListHelper(const InitListExpr *InitList); + RecordInitListHelper(const CXXParenListInitExpr *ParenInitList); // Base classes with their associated initializer expressions. ArrayRef> base_inits() const { @@ -68,6 +69,9 @@ public: } private: + RecordInitListHelper(QualType Ty, std::vector Fields, + ArrayRef Inits); + SmallVector> BaseInits; SmallVector> FieldInits; diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index 4277792219c0af2fbbb4563a8cf83fedb396fd54..d50dba35f8264c924d2c21ec3ac69485881fdb3a 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -84,7 +84,7 @@ public: virtual ComparisonResult compare(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2) { - // FIXME: Consider adding QualType to RecordValue and removing the Type + // FIXME: Consider adding `QualType` to `Value` and removing the `Type` // argument here. return ComparisonResult::Unknown; } @@ -407,20 +407,15 @@ public: /// storage locations and values for indirections until it finds a /// non-pointer/non-reference type. /// - /// If `Type` is a class, struct, or union type, creates values for all - /// modeled fields (including synthetic fields) and calls `setValue()` to - /// associate the `RecordValue` with its storage location - /// (`RecordValue::getLoc()`). - /// /// If `Type` is one of the following types, this function will always return /// a non-null pointer: /// - `bool` /// - Any integer type - /// - Any class, struct, or union type /// /// Requirements: /// - /// `Type` must not be null. + /// - `Type` must not be null. + /// - `Type` must not be a reference type or record type. Value *createValue(QualType Type); /// Creates an object (i.e. a storage location with an associated value) of @@ -452,6 +447,7 @@ public: /// Initializes the fields (including synthetic fields) of `Loc` with values, /// unless values of the field type are not supported or we hit one of the /// limits at which we stop producing values. + /// If a field already has a value, that value is preserved. /// If `Type` is provided, initializes only those fields that are modeled for /// `Type`; this is intended for use in cases where `Loc` is a derived type /// and we only want to initialize the fields of a base type. @@ -461,6 +457,10 @@ public: } /// Assigns `Val` as the value of `Loc` in the environment. + /// + /// Requirements: + /// + /// `Loc` must not be a `RecordStorageLocation`. void setValue(const StorageLocation &Loc, Value &Val); /// Clears any association between `Loc` and a value in the environment. @@ -470,20 +470,24 @@ public: /// /// Requirements: /// - /// - `E` must be a prvalue - /// - If `Val` is a `RecordValue`, its `RecordStorageLocation` must be - /// `getResultObjectLocation(E)`. An exception to this is if `E` is an - /// expression that originally creates a `RecordValue` (such as a - /// `CXXConstructExpr` or `CallExpr`), as these establish the location of - /// the result object in the first place. + /// - `E` must be a prvalue. + /// - `E` must not have record type. void setValue(const Expr &E, Value &Val); /// Returns the value assigned to `Loc` in the environment or null if `Loc` /// isn't assigned a value in the environment. + /// + /// Requirements: + /// + /// `Loc` must not be a `RecordStorageLocation`. Value *getValue(const StorageLocation &Loc) const; /// Equivalent to `getValue(getStorageLocation(D))` if `D` is assigned a /// storage location in the environment, otherwise returns null. + /// + /// Requirements: + /// + /// `D` must not have record type. Value *getValue(const ValueDecl &D) const; /// Equivalent to `getValue(getStorageLocation(E, SP))` if `E` is assigned a @@ -775,12 +779,6 @@ RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE, RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, const Environment &Env); -/// Associates a new `RecordValue` with `Loc` and returns the new value. -RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env); - -/// Associates a new `RecordValue` with `Expr` and returns the new value. -RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env); - } // namespace dataflow } // namespace clang diff --git a/clang/include/clang/Analysis/FlowSensitive/Value.h b/clang/include/clang/Analysis/FlowSensitive/Value.h index be1bf9324c87b40583b693ff6044d0f8d2211df6..97efa3a93ce6d9d9c58d435bd65aba255ebbc477 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Value.h +++ b/clang/include/clang/Analysis/FlowSensitive/Value.h @@ -35,7 +35,6 @@ public: enum class Kind { Integer, Pointer, - Record, // TODO: Top values should not be need to be type-specific. TopBool, @@ -67,7 +66,6 @@ public: /// Properties may not be set on `RecordValue`s; use synthetic fields instead /// (for details, see documentation for `RecordStorageLocation`). void setProperty(llvm::StringRef Name, Value &Val) { - assert(getKind() != Kind::Record); Properties.insert_or_assign(Name, &Val); } @@ -184,45 +182,6 @@ private: StorageLocation &PointeeLoc; }; -/// Models a value of `struct` or `class` type. -/// In C++, prvalues of class type serve only a limited purpose: They can only -/// be used to initialize a result object. It is not possible to access member -/// variables or call member functions on a prvalue of class type. -/// Correspondingly, `RecordValue` also serves only a limited purpose: It -/// conveys a prvalue of class type from the place where the object is -/// constructed to the result object that it initializes. -/// -/// When creating a prvalue of class type, we already need a storage location -/// for `this`, even though prvalues are otherwise not associated with storage -/// locations. `RecordValue` is therefore essentially a wrapper for a storage -/// location, which is then used to set the storage location for the result -/// object when we process the AST node for that result object. -/// -/// For example: -/// MyStruct S = MyStruct(3); -/// -/// In this example, `MyStruct(3) is a prvalue, which is modeled as a -/// `RecordValue` that wraps a `RecordStorageLocation`. This -/// `RecordStorageLocation` is then used as the storage location for `S`. -/// -/// Over time, we may eliminate `RecordValue` entirely. See also the discussion -/// here: https://reviews.llvm.org/D155204#inline-1503204 -class RecordValue final : public Value { -public: - explicit RecordValue(RecordStorageLocation &Loc) - : Value(Kind::Record), Loc(Loc) {} - - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Record; - } - - /// Returns the storage location that this `RecordValue` is associated with. - RecordStorageLocation &getLoc() const { return Loc; } - -private: - RecordStorageLocation &Loc; -}; - raw_ostream &operator<<(raw_ostream &OS, const Value &Val); } // namespace dataflow diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index 7cd3edf08a17eadb3ae0965e8747654f4e66a593..b94f6aef9ac60bf142d00a6be0c5c533107a80c9 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -129,6 +129,9 @@ DEBUGOPT(CodeViewCommandLine, 1, 0) /// Whether emit extra debug info for sample pgo profile collection. DEBUGOPT(DebugInfoForProfiling, 1, 0) +/// Whether to emit DW_TAG_template_alias for template aliases. +DEBUGOPT(DebugTemplateAlias, 1, 0) + /// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames. DEBUGOPT(DebugNameTable, 2, 0) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 47747d8704b6c85413312beb703c6800f6173893..5251774ff4efd6d7f607431511991ca633d22252 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1412,9 +1412,6 @@ 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">; diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index 396bff0146a373c94de9bd2c425c13e6c8e59083..91a40cd589b385d3adb8eefbc17bca90fabd0491 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -24,6 +24,7 @@ def err_no_matching_target : Error<"no matching target found for target variant def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">; def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">; def err_unsupported_os : Error<"os '%0' is not supported: '%1'">; +def err_cannot_read_alias_list : Error<"could not read alias list '%0': %1">; } // end of command line category. let CategoryName = "Verification" in { diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index bb9ca2a50cc06c36cbea45f4b4917a382433c7e2..66405095d51de84ce145cb4bbb86dbca3cb16b5a 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -863,6 +863,8 @@ def err_empty_requires_expr : Error< "a requires expression must contain at least one requirement">; def err_requires_expr_parameter_list_ellipsis : Error< "varargs not allowed in requires expression">; +def err_requires_expr_explicit_object_parameter: Error< + "a requires expression cannot have an explicit object parameter">; def err_expected_semi_requirement : Error< "expected ';' at end of requirement">; def err_requires_expr_missing_arrow : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 44f802c0c28e8415ec700c939c40f6b7dba76c1d..1a2d8bf4e4eb1513aee713118201b4257c4bd6b6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3669,6 +3669,9 @@ def warn_attribute_dllexport_explicit_instantiation_decl : Warning< def warn_attribute_dllexport_explicit_instantiation_def : Warning< "'dllexport' attribute ignored on explicit instantiation definition">, InGroup; +def warn_attribute_exclude_from_explicit_instantiation_local_class : Warning< + "%0 attribute ignored on local class%select{| member}1">, + InGroup; def warn_invalid_initializer_from_system_header : Warning< "invalid constructor from class in system header, should not be explicit">, InGroup>; @@ -3751,16 +3754,6 @@ 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< @@ -12278,4 +12271,16 @@ def warn_acc_if_self_conflict : Warning<"OpenACC construct 'self' has no effect when an 'if' clause " "evaluates to true">, InGroup>; +def err_acc_int_expr_requires_integer + : Error<"OpenACC %select{clause|directive}0 '%1' requires expression of " + "integer type (%2 invalid)">; +def err_acc_int_expr_incomplete_class_type + : Error<"OpenACC integer expression has incomplete class type %0">; +def err_acc_int_expr_explicit_conversion + : Error<"OpenACC integer expression type %0 requires explicit conversion " + "to %1">; +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">; } // end of sema component. diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index 378495d2c0909a55c595f21cd0805c1fbe21fdf8..520e068f4ffd403cb523445fa8cb866dd24c9832 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -18,5 +18,7 @@ VISIT_CLAUSE(Default) VISIT_CLAUSE(If) VISIT_CLAUSE(Self) +VISIT_CLAUSE(NumWorkers) +VISIT_CLAUSE(VectorLength) #undef VISIT_CLAUSE diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td index 87a18e8474ef5031a00f1dcf5dfc0fee55c23d12..76ed544f3b2bb1f2e0176932098b732613ec1b7a 100644 --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -357,13 +357,13 @@ multiclass RVVNonTupleVCreateBuiltin src_lmul_list> { defvar src_s = FixedVString.S; def vcreate # src_v # dst_v : RVVBuiltin; + "csilxfd">; defvar src_uv = FixedVString.V; defvar src_us = FixedVString.S; def vcreate_u # src_uv # dst_uv : RVVBuiltin; + "csil">; } } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e24626913add7627602398ab4f556b4340ec5d2f..d83031b05cebc475448d7f792b3afacf456f028b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1505,6 +1505,7 @@ def end_no_unused_arguments : Flag<["--"], "end-no-unused-arguments">, def interface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">, Visibility<[ClangOption, CC1Option]>; def exported__symbols__list : Separate<["-"], "exported_symbols_list">; +def alias_list : Separate<["-"], "alias_list">, Flags<[LinkerInput]>; def extract_api : Flag<["-"], "extract-api">, Visibility<[ClangOption, CC1Option]>, Group, HelpText<"Extract API information">; @@ -4308,6 +4309,8 @@ def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group, Values<"split,single">; def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group, Visibility<[ClangOption, CLOption, DXCOption]>; +def gtemplate_alias : Flag<["-"], "gtemplate-alias">, Group, Visibility<[ClangOption, CC1Option]>; +def gno_template_alias : Flag<["-"], "gno-template-alias">, Group, Visibility<[ClangOption]>; def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group; def gsimple_template_names_EQ : Joined<["-"], "gsimple-template-names=">, @@ -8343,14 +8346,15 @@ def _SLASH_FI : CLJoinedOrSeparate<"FI">, def _SLASH_Fe : CLJoined<"Fe">, HelpText<"Set output executable file name">, MetaVarName<"">; -def _SLASH_Fe_COLON : CLJoined<"Fe:">, Alias<_SLASH_Fe>; +def _SLASH_Fe_COLON : CLJoinedOrSeparate<"Fe:">, Alias<_SLASH_Fe>; def _SLASH_Fi : CLCompileJoined<"Fi">, HelpText<"Set preprocess output file name (with /P)">, MetaVarName<"">; +def _SLASH_Fi_COLON : CLJoinedOrSeparate<"Fi:">, Alias<_SLASH_Fi>; def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file (with /c)">, MetaVarName<"">; -def _SLASH_Fo_COLON : CLCompileJoined<"Fo:">, Alias<_SLASH_Fo>; +def _SLASH_Fo_COLON : CLCompileJoinedOrSeparate<"Fo:">, Alias<_SLASH_Fo>; def _SLASH_guard : CLJoined<"guard:">, HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks. " "Enable EH Continuation Guard with /guard:ehcont">; @@ -8445,6 +8449,7 @@ def _SLASH_Zc_dllexportInlines_ : CLFlag<"Zc:dllexportInlines-">, HelpText<"Do not dllexport/dllimport inline member functions of dllexport/import classes">; def _SLASH_Fp : CLJoined<"Fp">, HelpText<"Set pch file name (with /Yc and /Yu)">, MetaVarName<"">; +def _SLASH_Fp_COLON : CLJoinedOrSeparate<"Fp:">, Alias<_SLASH_Fp>; def _SLASH_Gd : CLFlag<"Gd">, HelpText<"Set __cdecl as a default calling convention">; diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h index 31de212fc423a5e8548d894c2ac26e3a4a225ae8..ae0428abbb9c71cb8c28a93d06dcf4bda50542fe 100644 --- a/clang/include/clang/InstallAPI/DylibVerifier.h +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -78,10 +78,12 @@ public: DylibVerifier() = default; DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports, - DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered, - bool Demangle, StringRef DSYMPath) - : Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode), - Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath), + AliasMap Aliases, DiagnosticsEngine *Diag, + VerificationMode Mode, bool Zippered, bool Demangle, + StringRef DSYMPath) + : Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), + Aliases(std::move(Aliases)), Mode(Mode), Zippered(Zippered), + Demangle(Demangle), DSYMPath(DSYMPath), Exports(std::make_unique()), Ctx(VerifierContext{Diag}) {} Result verify(GlobalRecord *R, const FrontendAttrs *FA); @@ -104,7 +106,7 @@ public: void setTarget(const Target &T); /// Release ownership over exports. - std::unique_ptr getExports() { return std::move(Exports); } + std::unique_ptr takeExports(); /// Get result of verification. Result getState() const { return Ctx.FrontendState; } @@ -189,6 +191,9 @@ private: // Reexported interfaces apart of the library. ReexportedInterfaces Reexports; + // Symbol aliases. + AliasMap Aliases; + // Controls what class of violations to report. VerificationMode Mode = VerificationMode::Invalid; diff --git a/clang/include/clang/InstallAPI/MachO.h b/clang/include/clang/InstallAPI/MachO.h index 854399f54ba6c84cea32fac9c66f78f67a46b6d1..9da91a62e233116b29d8beef474ef43ef43b47e7 100644 --- a/clang/include/clang/InstallAPI/MachO.h +++ b/clang/include/clang/InstallAPI/MachO.h @@ -23,6 +23,7 @@ #include "llvm/TextAPI/TextAPIWriter.h" #include "llvm/TextAPI/Utils.h" +using AliasMap = llvm::MachO::AliasMap; using Architecture = llvm::MachO::Architecture; using ArchitectureSet = llvm::MachO::ArchitectureSet; using SymbolFlags = llvm::MachO::SymbolFlags; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 23b268126de4e0be3fcc53bbded85d7df4804a6a..72b2f958a5e622e90343b733dbd60aab0a26ed97 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3640,13 +3640,14 @@ private: /// Parses the clause-list for an OpenACC directive. SmallVector ParseOpenACCClauseList(OpenACCDirectiveKind DirKind); - bool ParseOpenACCWaitArgument(); + bool ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective); /// Parses the clause of the 'bind' argument, which can be a string literal or /// an ID expression. ExprResult ParseOpenACCBindClauseArgument(); /// Parses the clause kind of 'int-expr', which can be any integral /// expression. - ExprResult ParseOpenACCIntExpr(); + ExprResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + SourceLocation Loc); /// Parses the 'device-type-list', which is a list of identifiers. bool ParseOpenACCDeviceTypeList(); /// Parses the 'async-argument', which is an integral value with two @@ -3657,9 +3658,9 @@ private: /// Parses a comma delimited list of 'size-expr's. bool ParseOpenACCSizeExprList(); /// Parses a 'gang-arg-list', used for the 'gang' clause. - bool ParseOpenACCGangArgList(); + bool ParseOpenACCGangArgList(SourceLocation GangLoc); /// Parses a 'gang-arg', used for the 'gang' clause. - bool ParseOpenACCGangArg(); + bool ParseOpenACCGangArg(SourceLocation GangLoc); /// Parses a 'condition' expr, ensuring it results in a ExprResult ParseOpenACCConditionExpr(); diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h index 2f2f2607a937fe1d27c88b61aaad88ac929d246b..0db5b847038ffdea0ef85bc81b1e3c11d8e1ff69 100644 --- a/clang/include/clang/Sema/Lookup.h +++ b/clang/include/clang/Sema/Lookup.h @@ -153,28 +153,30 @@ public: using iterator = UnresolvedSetImpl::iterator; - LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo, - Sema::LookupNameKind LookupKind, - Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) + LookupResult( + Sema &SemaRef, const DeclarationNameInfo &NameInfo, + Sema::LookupNameKind LookupKind, + RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration) : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind), - Redecl(Redecl != Sema::NotForRedeclaration), - ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), - DiagnoseAccess(Redecl == Sema::NotForRedeclaration), - DiagnoseAmbiguous(Redecl == Sema::NotForRedeclaration) { + Redecl(Redecl != RedeclarationKind::NotForRedeclaration), + ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration), + DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration), + DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) { configure(); } // TODO: consider whether this constructor should be restricted to take // as input a const IdentifierInfo* (instead of Name), // forcing other cases towards the constructor taking a DNInfo. - LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, - Sema::LookupNameKind LookupKind, - Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) + LookupResult( + Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, + Sema::LookupNameKind LookupKind, + RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration) : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind), - Redecl(Redecl != Sema::NotForRedeclaration), - ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), - DiagnoseAccess(Redecl == Sema::NotForRedeclaration), - DiagnoseAmbiguous(Redecl == Sema::NotForRedeclaration) { + Redecl(Redecl != RedeclarationKind::NotForRedeclaration), + ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration), + DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration), + DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) { configure(); } @@ -285,9 +287,10 @@ public: return ExternalRedecl; } - Sema::RedeclarationKind redeclarationKind() const { - return ExternalRedecl ? Sema::ForExternalRedeclaration : - Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration; + RedeclarationKind redeclarationKind() const { + return ExternalRedecl ? RedeclarationKind::ForExternalRedeclaration + : Redecl ? RedeclarationKind::ForVisibleRedeclaration + : RedeclarationKind::NotForRedeclaration; } /// Specify whether hidden declarations are visible, e.g., @@ -615,9 +618,9 @@ public: } /// Change this lookup's redeclaration kind. - void setRedeclarationKind(Sema::RedeclarationKind RK) { - Redecl = (RK != Sema::NotForRedeclaration); - ExternalRedecl = (RK == Sema::ForExternalRedeclaration); + void setRedeclarationKind(RedeclarationKind RK) { + Redecl = (RK != RedeclarationKind::NotForRedeclaration); + ExternalRedecl = (RK == RedeclarationKind::ForExternalRedeclaration); configure(); } diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index e3857b2f07d9e06978815721228c25fa5037e9e8..25a5fa05b21c7d8ab1054231de0af5f109b74227 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -94,7 +94,7 @@ struct PropertyData { : GetterId(getterId), SetterId(setterId) {} }; -} // namespace +} // namespace detail /// Wraps an identifier and optional source location for the identifier. struct IdentifierLoc { @@ -743,11 +743,6 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc = SourceLocation()) { - size_t temp = - ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0, 0); - (void)temp; void *memory = allocate( ParsedAttr::totalSizeToAlloc TypoRecoveryCallback; - /// Specifies whether (or how) name lookup is being performed for a - /// redeclaration (vs. a reference). - enum RedeclarationKind { - /// The lookup is a reference to this name that is not for the - /// purpose of redeclaring the name. - NotForRedeclaration = 0, - /// The lookup results will be used for redeclaration of a name, - /// if an entity by that name already exists and is visible. - ForVisibleRedeclaration, - /// The lookup results will be used for redeclaration of a name - /// with external linkage; non-visible lookup results with external linkage - /// may also be found. - ForExternalRedeclaration - }; - - RedeclarationKind forRedeclarationInCurContext() const { - // A declaration with an owning module for linkage can never link against - // anything that is not visible. We don't need to check linkage here; if - // the context has internal linkage, redeclaration lookup won't find things - // from other TUs, and we can't safely compute linkage yet in general. - if (cast(CurContext) - ->getOwningModuleForLinkage(/*IgnoreLinkage*/ true)) - return ForVisibleRedeclaration; - return ForExternalRedeclaration; - } + RedeclarationKind forRedeclarationInCurContext() const; /// Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. /// /// It is preferable to use the elaborated form and explicitly handle /// ambiguity and overloaded. - NamedDecl *LookupSingleName(Scope *S, DeclarationName Name, - SourceLocation Loc, LookupNameKind NameKind, - RedeclarationKind Redecl = NotForRedeclaration); + NamedDecl *LookupSingleName( + Scope *S, DeclarationName Name, SourceLocation Loc, + LookupNameKind NameKind, + RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration); bool LookupBuiltin(LookupResult &R); void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID); bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false, @@ -7488,9 +7466,9 @@ public: bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); - ObjCProtocolDecl * - LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, - RedeclarationKind Redecl = NotForRedeclaration); + ObjCProtocolDecl *LookupProtocol( + IdentifierInfo *II, SourceLocation IdLoc, + RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration); bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 329dc3945fa2a60f84b22a177c46ef27d1c9942c..023722049732afe03d3b655af4ab50f5c2a8119a 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -44,8 +44,13 @@ public: Expr *ConditionExpr; }; - std::variant Details = - std::monostate{}; + struct IntExprDetails { + SmallVector IntExprs; + }; + + std::variant + Details = std::monostate{}; public: OpenACCParsedClause(OpenACCDirectiveKind DirKind, @@ -87,6 +92,24 @@ public: return std::get(Details).ConditionExpr; } + unsigned getNumIntExprs() const { + assert((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 || + ClauseKind == OpenACCClauseKind::VectorLength) && + "Parsed clause kind does not have a int exprs"); + return std::get(Details).IntExprs; + } + + ArrayRef getIntExprs() const { + return const_cast(this)->getIntExprs(); + } + void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } @@ -109,6 +132,13 @@ public: Details = ConditionDetails{ConditionExpr}; } + + void setIntExprDetails(ArrayRef IntExprs) { + assert((ClauseKind == OpenACCClauseKind::NumWorkers || + ClauseKind == OpenACCClauseKind::VectorLength) && + "Parsed clause kind does not have a int exprs"); + Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}}; + } }; SemaOpenACC(Sema &S); @@ -148,6 +178,11 @@ public: /// Called after the directive has been completely parsed, including the /// declaration group or associated statement. DeclGroupRef ActOnEndDeclDirective(); + + /// Called when encountering an 'int-expr' for OpenACC, and manages + /// conversions and diagnostics to 'int'. + ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + SourceLocation Loc, Expr *IntExpr); }; } // namespace clang diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 43ee06c524b3a0b75b9f9d3158890cce4803a736..1cd8b6a357cbf9575db6220956642d4450c81f60 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -501,6 +501,8 @@ private: /// = I + 1 has already been loaded. llvm::PagedVector DeclsLoaded; + static_assert(std::is_same_v); + using GlobalDeclMapType = ContinuousRangeMap; diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 443f77031047006df8108f26570a669f30fc5c75..13b4ad4ad2953dba072d56eec9ff2c033cfb8a45 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -399,6 +399,11 @@ private: /// record containing modifications to them. DeclUpdateMap DeclUpdates; + /// DeclUpdates added during parsing the GMF. We split these from + /// DeclUpdates since we want to add these updates in GMF on need. + /// Only meaningful for reduced BMI. + DeclUpdateMap DeclUpdatesFromGMF; + using FirstLatestDeclMap = llvm::DenseMap; /// Map of first declarations from a chained PCH that point to the @@ -554,6 +559,8 @@ private: void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteDeclAndTypes(ASTContext &Context); + void PrepareWritingSpecialDecls(Sema &SemaRef); + void WriteSpecialDeclRecords(Sema &SemaRef); void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord); void WriteDeclContextVisibleUpdate(const DeclContext *DC); void WriteFPPragmaOptions(const FPOptionsOverride &Opts); @@ -707,6 +714,8 @@ public: /// Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordDataImpl &Record); + // Emit a reference to a declaration if the declaration was emitted. + void AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record); /// Force a declaration to be emitted and get its ID. serialization::DeclID GetDeclRef(const Decl *D); @@ -866,6 +875,11 @@ private: void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; void AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) override; + void EnteringModulePurview() override; + void AddedManglingNumber(const Decl *D, unsigned) override; + void AddedStaticLocalNumbers(const Decl *D, unsigned) override; + void AddedAnonymousNamespace(const TranslationUnitDecl *, + NamespaceDecl *AnonNamespace) override; }; /// AST and semantic-analysis consumer that generates a diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index d8042321319a67b253b034d8a0d4572a97f14d2f..8c77b563657d9073aa6cde9035d47c52cd9c32f0 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -908,7 +908,8 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, for (const auto *FI : RD->fields()) { if (!First) Out << ", "; - if (FI->isUnnamedBitfield()) continue; + if (FI->isUnnamedBitField()) + continue; getStructField(FI->getFieldIndex()). printPretty(Out, Policy, FI->getType(), Ctx); First = false; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 6ce233704a5885ab27094b8db7614bd98ef95b9e..b974fc28283c775ee1a24ae7c9cb67f3bc99c0e6 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2684,7 +2684,7 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context, if (Field->isBitField()) { // If we have explicit padding bits, they don't contribute bits // to the actual object representation, so return 0. - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) return 0; int64_t BitfieldSize = Field->getBitWidthValue(Context); @@ -12245,8 +12245,13 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth, } void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) { - if (Number > 1) - MangleNumbers[ND] = Number; + if (Number <= 1) + return; + + MangleNumbers[ND] = Number; + + if (Listener) + Listener->AddedManglingNumber(ND, Number); } unsigned ASTContext::getManglingNumber(const NamedDecl *ND, @@ -12265,8 +12270,13 @@ unsigned ASTContext::getManglingNumber(const NamedDecl *ND, } void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) { - if (Number > 1) - StaticLocalNumbers[VD] = Number; + if (Number <= 1) + return; + + StaticLocalNumbers[VD] = Number; + + if (Listener) + Listener->AddedStaticLocalNumbers(VD, Number); } unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 33b6f8611f216245fd1128514eb173f7089a1301..474e0ccde5bbf793369028e9fee2a2d6660032f1 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2151,7 +2151,7 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); } -VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +VarDecl *VarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr, QualType(), nullptr, SC_None); @@ -2929,7 +2929,7 @@ QualType ParmVarDecl::getOriginalType() const { return T; } -ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(), nullptr, QualType(), nullptr, SC_None, nullptr); @@ -4553,7 +4553,7 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, BW, Mutable, InitStyle); } -FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(), SourceLocation(), nullptr, QualType(), nullptr, nullptr, false, ICIS_NoInit); @@ -4597,7 +4597,7 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { } bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const { - return isUnnamedBitfield() && !getBitWidth()->isValueDependent() && + return isUnnamedBitField() && !getBitWidth()->isValueDependent() && getBitWidthValue(Ctx) == 0; } @@ -4863,7 +4863,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, return Enum; } -EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { EnumDecl *Enum = new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr, false, false, false); @@ -5025,7 +5025,7 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, return R; } -RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { +RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) { RecordDecl *R = new (C, ID) RecordDecl(Record, TagTypeKind::Struct, C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); @@ -5274,6 +5274,13 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); } +void TranslationUnitDecl::setAnonymousNamespace(NamespaceDecl *D) { + AnonymousNamespace = D; + + if (ASTMutationListener *Listener = Ctx.getASTMutationListener()) + Listener->AddedAnonymousNamespace(this, D); +} + void PragmaCommentDecl::anchor() {} PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C, @@ -5290,7 +5297,7 @@ PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C, } PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C, - unsigned ID, + Decl::DeclID ID, unsigned ArgSize) { return new (C, ID, additionalSizeToAlloc(ArgSize + 1)) PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown); @@ -5315,7 +5322,7 @@ PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC, } PragmaDetectMismatchDecl * -PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID, +PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NameValueSize) { return new (C, ID, additionalSizeToAlloc(NameValueSize + 1)) PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0); @@ -5342,7 +5349,7 @@ LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL); } -LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr, SourceLocation()); } @@ -5383,7 +5390,7 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type, } ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); } @@ -5401,7 +5408,7 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, return New; } -FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) FunctionDecl( Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr); @@ -5411,7 +5418,7 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { return new (C, DC) BlockDecl(DC, L); } -BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) BlockDecl(nullptr, SourceLocation()); } @@ -5425,7 +5432,7 @@ CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC, CapturedDecl(DC, NumParams); } -CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID, +CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NumParams) { return new (C, ID, additionalSizeToAlloc(NumParams)) CapturedDecl(nullptr, NumParams); @@ -5452,7 +5459,7 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, } EnumConstantDecl * -EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +EnumConstantDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) EnumConstantDecl(C, nullptr, SourceLocation(), nullptr, QualType(), nullptr, llvm::APSInt()); } @@ -5479,7 +5486,7 @@ IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(), QualType(), std::nullopt); @@ -5540,7 +5547,7 @@ bool TypedefNameDecl::isTransparentTagSlow() const { return isTransparent; } -TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); } @@ -5553,7 +5560,7 @@ TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } -TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); } @@ -5584,7 +5591,7 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, } FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(), SourceLocation()); } @@ -5602,7 +5609,7 @@ TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) { } TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) TopLevelStmtDecl(/*DC=*/nullptr, SourceLocation(), /*S=*/nullptr); } @@ -5623,7 +5630,7 @@ EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { return new (C, DC) EmptyDecl(DC, L); } -EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) EmptyDecl(nullptr, SourceLocation()); } @@ -5656,7 +5663,7 @@ HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C, return Result; } -HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr, SourceLocation(), SourceLocation()); } @@ -5712,7 +5719,7 @@ ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, return Import; } -ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, +ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NumLocations) { return new (C, ID, additionalSizeToAlloc(NumLocations)) ImportDecl(EmptyShell()); @@ -5745,6 +5752,6 @@ ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC, return new (C, DC) ExportDecl(DC, ExportLoc); } -ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ExportDecl(nullptr, SourceLocation()); } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 434926324c96ca25dea83258a27924d3cd9a3da2..7cb6b31c541fd373662921cc8e46de533d9c16f7 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -71,7 +71,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { #include "clang/AST/DeclNodes.inc" void *Decl::operator new(std::size_t Size, const ASTContext &Context, - unsigned ID, std::size_t Extra) { + Decl::DeclID ID, std::size_t Extra) { // Allocate an extra 8 bytes worth of storage, which ensures that the // resulting pointer will still be 8-byte aligned. static_assert(sizeof(unsigned) * 2 >= alignof(Decl), diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 645ec2f7563bca86bee1613a2dbec89247eafc87..426c5262051094b23d83023eacd2b0ac31abba65 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -57,7 +57,7 @@ using namespace clang; void AccessSpecDecl::anchor() {} -AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) AccessSpecDecl(EmptyShell()); } @@ -161,7 +161,7 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, } CXXRecordDecl * -CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { +CXXRecordDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) { auto *R = new (C, ID) CXXRecordDecl(CXXRecord, TagTypeKind::Struct, C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); @@ -668,7 +668,7 @@ bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType( for (auto *FD : X->fields()) { // FIXME: Should we really care about the type of the first non-static // data member of a non-union if there are preceding unnamed bit-fields? - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) continue; if (!IsFirstField && !FD->isZeroSize(Ctx)) @@ -947,7 +947,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // A declaration for a bit-field that omits the identifier declares an // unnamed bit-field. Unnamed bit-fields are not members and cannot be // initialized. - if (Field->isUnnamedBitfield()) { + if (Field->isUnnamedBitField()) { // C++ [meta.unary.prop]p4: [LWG2358] // T is a class type [...] with [...] no unnamed bit-fields of non-zero // length @@ -2163,7 +2163,7 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( } CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) CXXDeductionGuideDecl( C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), QualType(), nullptr, SourceLocation(), nullptr, @@ -2176,7 +2176,7 @@ RequiresExprBodyDecl *RequiresExprBodyDecl::Create( } RequiresExprBodyDecl *RequiresExprBodyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation()); } @@ -2281,7 +2281,7 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, isInline, ConstexprKind, EndLocation, TrailingRequiresClause); } -CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) CXXMethodDecl( CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, SC_None, false, false, @@ -2699,7 +2699,7 @@ CXXConstructorDecl::CXXConstructorDecl( void CXXConstructorDecl::anchor() {} CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, - unsigned ID, + Decl::DeclID ID, uint64_t AllocKind) { bool hasTrailingExplicit = static_cast(AllocKind & TAKHasTailExplicit); bool isInheritingConstructor = @@ -2846,7 +2846,7 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const { void CXXDestructorDecl::anchor() {} CXXDestructorDecl * -CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +CXXDestructorDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) CXXDestructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, false, false, false, ConstexprSpecKind::Unspecified, nullptr); @@ -2878,7 +2878,7 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { void CXXConversionDecl::anchor() {} CXXConversionDecl * -CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +CXXConversionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, @@ -2924,7 +2924,7 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, } LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) LinkageSpecDecl(nullptr, SourceLocation(), SourceLocation(), LinkageSpecLanguageIDs::C, false); @@ -2946,7 +2946,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, } UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) UsingDirectiveDecl(nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), @@ -2985,7 +2985,7 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, PrevDecl, Nested); } -NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(), SourceLocation(), nullptr, nullptr, false); } @@ -3047,7 +3047,7 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, } NamespaceAliasDecl * -NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +NamespaceAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) NamespaceAliasDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, NestedNameSpecifierLoc(), @@ -3103,7 +3103,7 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty) redeclarable_base(C) {} UsingShadowDecl * -UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +UsingShadowDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell()); } @@ -3126,7 +3126,7 @@ ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC, } ConstructorUsingShadowDecl * -ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell()); } @@ -3174,7 +3174,7 @@ UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, return new (C, DC) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); } -UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) UsingDecl(nullptr, SourceLocation(), NestedNameSpecifierLoc(), DeclarationNameInfo(), false); @@ -3198,7 +3198,7 @@ UsingEnumDecl *UsingEnumDecl::Create(ASTContext &C, DeclContext *DC, UsingEnumDecl(DC, EnumType->getType()->getAsTagDecl()->getDeclName(), UL, EL, NL, EnumType); } -UsingEnumDecl *UsingEnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +UsingEnumDecl *UsingEnumDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) UsingEnumDecl(nullptr, DeclarationName(), SourceLocation(), SourceLocation(), SourceLocation(), nullptr); @@ -3217,7 +3217,7 @@ UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls); } -UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, +UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NumExpansions) { size_t Extra = additionalSizeToAlloc(NumExpansions); auto *Result = @@ -3243,7 +3243,7 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, } UnresolvedUsingValueDecl * -UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(), SourceLocation(), NestedNameSpecifierLoc(), @@ -3273,7 +3273,7 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, } UnresolvedUsingTypenameDecl * -UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) UnresolvedUsingTypenameDecl( nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), nullptr, SourceLocation()); @@ -3286,7 +3286,7 @@ UnresolvedUsingIfExistsDecl::Create(ASTContext &Ctx, DeclContext *DC, } UnresolvedUsingIfExistsDecl * -UnresolvedUsingIfExistsDecl::CreateDeserialized(ASTContext &Ctx, unsigned ID) { +UnresolvedUsingIfExistsDecl::CreateDeserialized(ASTContext &Ctx, Decl::DeclID ID) { return new (Ctx, ID) UnresolvedUsingIfExistsDecl(nullptr, SourceLocation(), DeclarationName()); } @@ -3310,7 +3310,7 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, } StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) StaticAssertDecl(nullptr, SourceLocation(), nullptr, nullptr, SourceLocation(), false); } @@ -3332,7 +3332,7 @@ BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC, return new (C, DC) BindingDecl(DC, IdLoc, Id); } -BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr); } @@ -3363,7 +3363,7 @@ DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC, } DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, - unsigned ID, + Decl::DeclID ID, unsigned NumBindings) { size_t Extra = additionalSizeToAlloc(NumBindings); auto *Result = new (C, ID, Extra) @@ -3402,7 +3402,7 @@ MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC, } MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) MSPropertyDecl(nullptr, SourceLocation(), DeclarationName(), QualType(), nullptr, SourceLocation(), nullptr, nullptr); @@ -3419,7 +3419,7 @@ MSGuidDecl *MSGuidDecl::Create(const ASTContext &C, QualType T, Parts P) { return new (C, DC) MSGuidDecl(DC, T, P); } -MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts()); } @@ -3469,7 +3469,8 @@ static bool isValidStructGUID(ASTContext &Ctx, QualType T) { return false; auto MatcherIt = Fields.begin(); for (const FieldDecl *FD : RD->fields()) { - if (FD->isUnnamedBitfield()) continue; + if (FD->isUnnamedBitField()) + continue; if (FD->isBitField() || MatcherIt == Fields.end() || !(*MatcherIt)(FD->getType())) return false; @@ -3528,7 +3529,7 @@ UnnamedGlobalConstantDecl::Create(const ASTContext &C, QualType T, } UnnamedGlobalConstantDecl * -UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) UnnamedGlobalConstantDecl(C, nullptr, QualType(), APValue()); } diff --git a/clang/lib/AST/DeclFriend.cpp b/clang/lib/AST/DeclFriend.cpp index 8ec1dea84df5f19ed29c4e1068de854c87a0a68d..1fabf8aa80c2bdb66fca9e368f4d6f95a147038d 100644 --- a/clang/lib/AST/DeclFriend.cpp +++ b/clang/lib/AST/DeclFriend.cpp @@ -62,7 +62,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, return FD; } -FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID, +FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned FriendTypeNumTPLists) { std::size_t Extra = additionalSizeToAlloc(FriendTypeNumTPLists); diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 32c14938cd5888cd65a8dda612f5b996bf4a7f30..d4275eea058212976f056a3f72874d144e15f11f 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -862,7 +862,7 @@ ObjCMethodDecl *ObjCMethodDecl::Create( isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); } -ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(), Selector(), QualType(), nullptr, nullptr); } @@ -1486,7 +1486,7 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, } ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, - unsigned ID) { + Decl::DeclID ID) { return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr, ObjCTypeParamVariance::Invariant, SourceLocation(), 0, SourceLocation(), @@ -1551,7 +1551,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create( } ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { auto *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr, SourceLocation(), nullptr, false); @@ -1865,7 +1865,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, synthesized); } -ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(), nullptr, QualType(), nullptr, ObjCIvarDecl::None, nullptr, false); @@ -1914,7 +1914,7 @@ ObjCAtDefsFieldDecl } ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(), SourceLocation(), nullptr, QualType(), nullptr); @@ -1949,7 +1949,7 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, } ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { ObjCProtocolDecl *Result = new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(), SourceLocation(), nullptr); @@ -2148,7 +2148,7 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create( } ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(), SourceLocation(), SourceLocation(), nullptr, nullptr, nullptr); @@ -2189,7 +2189,7 @@ ObjCCategoryImplDecl *ObjCCategoryImplDecl::Create( } ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr, SourceLocation(), SourceLocation(), SourceLocation()); @@ -2296,7 +2296,7 @@ ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, } ObjCImplementationDecl * -ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ObjCImplementationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr, SourceLocation(), SourceLocation()); } @@ -2339,7 +2339,7 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, } ObjCCompatibleAliasDecl * -ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(), nullptr, nullptr); } @@ -2360,7 +2360,7 @@ ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, } ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr, SourceLocation(), SourceLocation(), QualType(), nullptr, None); @@ -2393,7 +2393,7 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, } ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(), SourceLocation(), nullptr, Dynamic, nullptr, SourceLocation()); diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp index ac5780f82dbbb23b68257274af7328dff45b2229..b178a15aab5f282363b48a29bfa252c9c2a1783b 100644 --- a/clang/lib/AST/DeclOpenMP.cpp +++ b/clang/lib/AST/DeclOpenMP.cpp @@ -36,7 +36,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, } OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, - unsigned ID, + Decl::DeclID ID, unsigned N) { return OMPDeclarativeDirective::createEmptyDirective( C, ID, 0, N); @@ -63,7 +63,7 @@ OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC, return D; } -OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID, +OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NVars, unsigned NClauses) { return OMPDeclarativeDirective::createEmptyDirective( @@ -89,7 +89,7 @@ OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC, L); } -OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, unsigned ID, +OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned N) { return OMPDeclarativeDirective::createEmptyDirective( C, ID, N, 0, SourceLocation()); @@ -117,7 +117,7 @@ OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create( } OMPDeclareReductionDecl * -OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) OMPDeclareReductionDecl( OMPDeclareReduction, /*DC=*/nullptr, SourceLocation(), DeclarationName(), QualType(), /*PrevDeclInScope=*/nullptr); @@ -148,7 +148,7 @@ OMPDeclareMapperDecl *OMPDeclareMapperDecl::Create( } OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C, - unsigned ID, + Decl::DeclID ID, unsigned N) { return OMPDeclarativeDirective::createEmptyDirective( C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(), @@ -179,7 +179,7 @@ OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC, } OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), /*TInfo=*/nullptr, SourceLocation()); } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 93857adb990bf209d3ccbff6e0016f2fbe0de4f8..599d379340abadf5ca921ab823f7218c0f07e223 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -119,7 +119,7 @@ namespace { void printTemplateArguments(llvm::ArrayRef Args, const TemplateParameterList *Params); enum class AttrPosAsWritten { Default = 0, Left, Right }; - void + bool prettyPrintAttributes(const Decl *D, AttrPosAsWritten Pos = AttrPosAsWritten::Default); void prettyPrintPragmas(Decl *D); @@ -252,16 +252,19 @@ static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A, return DeclPrinter::AttrPosAsWritten::Right; } -void DeclPrinter::prettyPrintAttributes(const Decl *D, +// returns true if an attribute was printed. +bool DeclPrinter::prettyPrintAttributes(const Decl *D, AttrPosAsWritten Pos /*=Default*/) { - if (Policy.PolishForDeclaration) - return; + bool hasPrinted = false; if (D->hasAttrs()) { const AttrVec &Attrs = D->getAttrs(); for (auto *A : Attrs) { if (A->isInherited() || A->isImplicit()) continue; + // Print out the keyword attributes, they aren't regular attributes. + if (Policy.PolishForDeclaration && !A->isKeywordAttribute()) + continue; switch (A->getKind()) { #define ATTR(X) #define PRAGMA_SPELLING_ATTR(X) case attr::X: @@ -275,6 +278,7 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D, if (Pos != AttrPosAsWritten::Left) Out << ' '; A->printPretty(Out, Policy); + hasPrinted = true; if (Pos == AttrPosAsWritten::Left) Out << ' '; } @@ -282,6 +286,7 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D, } } } + return hasPrinted; } void DeclPrinter::prettyPrintPragmas(Decl *D) { @@ -1065,12 +1070,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { // FIXME: add printing of pragma attributes if required. if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; - Out << D->getKindName(); - prettyPrintAttributes(D); + Out << D->getKindName() << ' '; - if (D->getIdentifier()) { + // FIXME: Move before printing the decl kind to match the behavior of the + // attribute printing for variables and function where they are printed first. + if (prettyPrintAttributes(D, AttrPosAsWritten::Left)) Out << ' '; + + if (D->getIdentifier()) { if (auto *NNS = D->getQualifier()) NNS->print(Out, Policy); Out << *D; @@ -1087,16 +1095,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { } } - if (D->hasDefinition()) { - if (D->hasAttr()) { - Out << " final"; - } - } + prettyPrintAttributes(D, AttrPosAsWritten::Right); if (D->isCompleteDefinition()) { + Out << ' '; // Print the base classes if (D->getNumBases()) { - Out << " : "; + Out << ": "; for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { if (Base != D->bases_begin()) @@ -1115,14 +1120,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { if (Base->isPackExpansion()) Out << "..."; } + Out << ' '; } // Print the class definition // FIXME: Doesn't print access specifiers, e.g., "public:" if (Policy.TerseOutput) { - Out << " {}"; + Out << "{}"; } else { - Out << " {\n"; + Out << "{\n"; VisitDeclContext(D); Indent() << "}"; } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 5aa2484197372bae11343ba22335c1734023ca1d..0ba271c3e04ee5ddf91cb5138c8e77dfadd4ff54 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -418,7 +418,7 @@ FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, } FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(), DeclarationName(), nullptr, nullptr); } @@ -503,7 +503,7 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC, } ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(), DeclarationName(), nullptr, nullptr); } @@ -652,14 +652,14 @@ TemplateTypeParmDecl *TemplateTypeParmDecl::Create( } TemplateTypeParmDecl * -TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { +TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) { return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr, false, false, std::nullopt); } TemplateTypeParmDecl * -TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID, +TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID, bool HasTypeConstraint) { return new (C, ID, additionalSizeToAlloc(HasTypeConstraint ? 1 : 0)) @@ -759,7 +759,7 @@ NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create( } NonTypeTemplateParmDecl * -NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, +NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, bool HasTypeConstraint) { return new (C, ID, additionalSizeToAlloc, @@ -770,7 +770,7 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, } NonTypeTemplateParmDecl * -NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, +NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NumExpandedTypes, bool HasTypeConstraint) { auto *NTTP = @@ -836,13 +836,13 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, } TemplateTemplateParmDecl * -TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, false, nullptr, false, nullptr); } TemplateTemplateParmDecl * -TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, +TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID, unsigned NumExpansions) { auto *TTP = new (C, ID, additionalSizeToAlloc(NumExpansions)) @@ -949,7 +949,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { auto *Result = new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization); Result->setMayHaveOutOfDateDef(false); @@ -1036,7 +1036,7 @@ ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC, } ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(), DeclarationName(), nullptr, nullptr); @@ -1070,7 +1070,7 @@ ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create( ImplicitConceptSpecializationDecl * ImplicitConceptSpecializationDecl::CreateDeserialized( - const ASTContext &C, unsigned ID, unsigned NumTemplateArgs) { + const ASTContext &C, Decl::DeclID ID, unsigned NumTemplateArgs) { return new (C, ID, additionalSizeToAlloc(NumTemplateArgs)) ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs); } @@ -1133,7 +1133,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C); Result->setMayHaveOutOfDateDef(false); return Result; @@ -1160,7 +1160,7 @@ FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, } FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) FriendTemplateDecl(EmptyShell()); } @@ -1180,7 +1180,7 @@ TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, } TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(), DeclarationName(), nullptr, nullptr); } @@ -1218,7 +1218,7 @@ VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC, } VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(), DeclarationName(), nullptr, nullptr); } @@ -1340,7 +1340,7 @@ VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create( } VarTemplateSpecializationDecl * -VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { return new (C, ID) VarTemplateSpecializationDecl(VarTemplateSpecialization, C); } @@ -1432,7 +1432,7 @@ VarTemplatePartialSpecializationDecl::Create( VarTemplatePartialSpecializationDecl * VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { + Decl::DeclID ID) { return new (C, ID) VarTemplatePartialSpecializationDecl(C); } @@ -1546,7 +1546,7 @@ TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C, } TemplateParamObjectDecl * -TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, unsigned ID) { +TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) { auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue()); C.addDestruction(&TPOD->Value); return TPOD; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 07c9f287dd0767208d783ad14d88169f7ba1efa0..9eec7edc9d1a3e16c02df045792be33f589f1011 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2044,7 +2044,7 @@ const FieldDecl *CastExpr::getTargetFieldForToUnionCast(const RecordDecl *RD, for (Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (Ctx.hasSameUnqualifiedType(Field->getType(), OpType) && - !Field->isUnnamedBitfield()) { + !Field->isUnnamedBitField()) { return *Field; } } @@ -3393,7 +3393,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, continue; // Don't emit anonymous bitfields, they just affect layout. - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; if (ElementNo < ILE->getNumInits()) { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 88c8eaf6ef9b6eb86b288828cd5066ae911cb365..73ae8d8efb23a28d372ef170bcb05ce7f4089882 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2492,7 +2492,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, } } for (const auto *I : RD->fields()) { - if (I->isUnnamedBitfield()) + if (I->isUnnamedBitField()) continue; if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(), @@ -3529,7 +3529,7 @@ static bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD) { return false; for (auto *Field : RD->fields()) - if (!Field->isUnnamedBitfield() && + if (!Field->isUnnamedBitField() && isReadByLvalueToRvalueConversion(Field->getType())) return true; @@ -4898,7 +4898,7 @@ static bool handleDefaultInitValue(QualType T, APValue &Result) { handleDefaultInitValue(I->getType(), Result.getStructBase(Index)); for (const auto *I : RD->fields()) { - if (I->isUnnamedBitfield()) + if (I->isUnnamedBitField()) continue; Success &= handleDefaultInitValue( I->getType(), Result.getStructField(I->getFieldIndex())); @@ -6436,7 +6436,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, // Default-initialize any fields with no explicit initializer. for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) { assert(FieldIt != RD->field_end() && "missing field?"); - if (!FieldIt->isUnnamedBitfield()) + if (!FieldIt->isUnnamedBitField()) Success &= handleDefaultInitValue( FieldIt->getType(), Result.getStructField(FieldIt->getFieldIndex())); @@ -6546,7 +6546,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, // Default-initialize any remaining fields. if (!RD->isUnion()) { for (; FieldIt != RD->field_end(); ++FieldIt) { - if (!FieldIt->isUnnamedBitfield()) + if (!FieldIt->isUnnamedBitField()) Success &= handleDefaultInitValue( FieldIt->getType(), Result.getStructField(FieldIt->getFieldIndex())); @@ -6708,7 +6708,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange, // fields first and then walk them backwards. SmallVector Fields(RD->fields()); for (const FieldDecl *FD : llvm::reverse(Fields)) { - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) continue; LValue Subobject = This; @@ -10220,7 +10220,7 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, for (const auto *I : RD->fields()) { // -- if T is a reference type, no initialization is performed. - if (I->isUnnamedBitfield() || I->getType()->isReferenceType()) + if (I->isUnnamedBitField() || I->getType()->isReferenceType()) continue; LValue Subobject = This; @@ -10243,7 +10243,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) { // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the // object's first non-static named data member is zero-initialized RecordDecl::field_iterator I = RD->field_begin(); - while (I != RD->field_end() && (*I)->isUnnamedBitfield()) + while (I != RD->field_end() && (*I)->isUnnamedBitField()) ++I; if (I == RD->field_end()) { Result = APValue((const FieldDecl*)nullptr); @@ -10390,7 +10390,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr( for (const auto *Field : RD->fields()) { // Anonymous bit-fields are not considered members of the class for // purposes of aggregate initialization. - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; LValue Subobject = This; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 6b4b51aac41e84dedc0ac8deb67c9ffa34565401..f317f506d24f4b9fe8f962d27fbe3f010899c4d4 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -971,6 +971,11 @@ bool ByteCodeExprGen::visitInitList(ArrayRef Inits, unsigned InitIndex = 0; for (const Expr *Init : Inits) { + // Skip unnamed bitfields. + while (InitIndex < R->getNumFields() && + R->getField(InitIndex)->Decl->isUnnamedBitField()) + ++InitIndex; + if (!this->emitDupPtr(E)) return false; @@ -1838,7 +1843,7 @@ bool ByteCodeExprGen::VisitCompoundLiteralExpr( const Expr *Init = E->getInitializer(); if (Initializing) { // We already have a value, just initialize that. - return this->visitInitializer(Init); + return this->visitInitializer(Init) && this->emitFinishInit(E); } std::optional T = classify(E->getType()); @@ -1857,7 +1862,7 @@ bool ByteCodeExprGen::VisitCompoundLiteralExpr( return this->emitInitGlobal(*T, *GlobalIndex, E); } - return this->visitInitializer(Init); + return this->visitInitializer(Init) && this->emitFinishInit(E); } return false; @@ -1886,7 +1891,7 @@ bool ByteCodeExprGen::VisitCompoundLiteralExpr( } return this->emitInit(*T, E); } else { - if (!this->visitInitializer(Init)) + if (!this->visitInitializer(Init) || !this->emitFinishInit(E)) return false; } @@ -3206,15 +3211,20 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { return false; if (!this->emitAddf(getRoundingMode(E), E)) return false; - return this->emitStoreFloat(E); + if (!this->emitStoreFloat(E)) + return false; + } else { + assert(isIntegralType(*T)); + if (!this->emitLoad(*T, E)) + return false; + if (!this->emitConst(1, E)) + return false; + if (!this->emitAdd(*T, E)) + return false; + if (!this->emitStore(*T, E)) + return false; } - if (!this->emitLoad(*T, E)) - return false; - if (!this->emitConst(1, E)) - return false; - if (!this->emitAdd(*T, E)) - return false; - return this->emitStore(*T, E); + return E->isGLValue() || this->emitLoadPop(*T, E); } case UO_PreDec: { // --x if (!this->visit(SubExpr)) @@ -3245,15 +3255,20 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { return false; if (!this->emitSubf(getRoundingMode(E), E)) return false; - return this->emitStoreFloat(E); + if (!this->emitStoreFloat(E)) + return false; + } else { + assert(isIntegralType(*T)); + if (!this->emitLoad(*T, E)) + return false; + if (!this->emitConst(1, E)) + return false; + if (!this->emitSub(*T, E)) + return false; + if (!this->emitStore(*T, E)) + return false; } - if (!this->emitLoad(*T, E)) - return false; - if (!this->emitConst(1, E)) - return false; - if (!this->emitSub(*T, E)) - return false; - return this->emitStore(*T, E); + return E->isGLValue() || this->emitLoadPop(*T, E); } case UO_LNot: // !x if (DiscardResult) diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index d567b551f7f6fcffbab18b4c067572f8f4960f15..e92d686c724cc8898e70eb10077532f6f117655f 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -105,7 +105,7 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord()); } else if (FieldType->isIncompleteArrayType()) { // Nothing to do here. - } else if (F.Decl->isUnnamedBitfield()) { + } else if (F.Decl->isUnnamedBitField()) { // Nothing do do here. } else if (FieldType->isArrayType()) { const auto *CAT = diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index e6f22e79451e970e06d5ab47744be4489d3b7715..2c8c6781b3483344f6f271c5b84c00993f44d1ff 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -312,6 +312,11 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { // Reserve space for fields. Record::FieldList Fields; for (const FieldDecl *FD : RD->fields()) { + // Note that we DO create fields and descriptors + // for unnamed bitfields here, even though we later ignore + // them everywhere. That's because so the FieldDecl's + // getFieldIndex() matches. + // Reserve space for the field's descriptor and the offset. BaseSize += align(sizeof(InlineDescriptor)); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d632c697fa20dbc4e88e15a6715f923020680b19..c3b98d2d2149cb589da0286d95f323b0b9e8783b 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6176,7 +6176,7 @@ static bool isZeroInitialized(QualType T, const APValue &V) { } I = 0; for (const FieldDecl *FD : RD->fields()) { - if (!FD->isUnnamedBitfield() && + if (!FD->isUnnamedBitField() && !isZeroInitialized(FD->getType(), V.getStructField(I))) return false; ++I; @@ -6189,7 +6189,7 @@ static bool isZeroInitialized(QualType T, const APValue &V) { assert(RD && "unexpected type for union value"); // Zero-initialization zeroes the first non-unnamed-bitfield field, if any. for (const FieldDecl *FD : RD->fields()) { - if (!FD->isUnnamedBitfield()) + if (!FD->isUnnamedBitField()) return V.getUnionField() && declaresSameEntity(FD, V.getUnionField()) && isZeroInitialized(FD->getType(), V.getUnionValue()); } @@ -6331,7 +6331,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, llvm::SmallVector Fields(RD->fields()); while ( !Fields.empty() && - (Fields.back()->isUnnamedBitfield() || + (Fields.back()->isUnnamedBitField() || isZeroInitialized(Fields.back()->getType(), V.getStructField(Fields.back()->getFieldIndex())))) { Fields.pop_back(); @@ -6351,7 +6351,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, for (unsigned I = 0, N = Bases.size(); I != N; ++I) mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I), false); for (unsigned I = 0, N = Fields.size(); I != N; ++I) { - if (Fields[I]->isUnnamedBitfield()) + if (Fields[I]->isUnnamedBitField()) continue; mangleValueInTemplateArg(Fields[I]->getType(), V.getStructField(Fields[I]->getFieldIndex()), diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index a0bb04e69c9be8ad244618fb51277344309811a6..36d611750ca48cd11b800fc26e495337e8abfc8c 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1933,7 +1933,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, for (const CXXBaseSpecifier &B : RD->bases()) mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++), TAK); for (const FieldDecl *FD : RD->fields()) - if (!FD->isUnnamedBitfield()) + if (!FD->isUnnamedBitField()) mangleTemplateArgValue(FD->getType(), V.getStructField(FD->getFieldIndex()), TAK, /*WithScalarType*/ true); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index 9c259c8f9bd0a1a620f4101633879555a4e0789e..75334223e073c32feb9c65d657a429826c8e8438 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -82,6 +82,48 @@ OpenACCClause::child_range OpenACCClause::children() { return child_range(child_iterator(), child_iterator()); } +OpenACCNumWorkersClause::OpenACCNumWorkersClause(SourceLocation BeginLoc, + SourceLocation LParenLoc, + Expr *IntExpr, + SourceLocation EndLoc) + : OpenACCClauseWithSingleIntExpr(OpenACCClauseKind::NumWorkers, BeginLoc, + LParenLoc, IntExpr, EndLoc) { + assert((!IntExpr || IntExpr->isInstantiationDependent() || + IntExpr->getType()->isIntegerType()) && + "Condition expression type not scalar/dependent"); +} + +OpenACCNumWorkersClause * +OpenACCNumWorkersClause::Create(const ASTContext &C, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *IntExpr, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OpenACCNumWorkersClause), + alignof(OpenACCNumWorkersClause)); + return new (Mem) + OpenACCNumWorkersClause(BeginLoc, LParenLoc, IntExpr, EndLoc); +} + +OpenACCVectorLengthClause::OpenACCVectorLengthClause(SourceLocation BeginLoc, + SourceLocation LParenLoc, + Expr *IntExpr, + SourceLocation EndLoc) + : OpenACCClauseWithSingleIntExpr(OpenACCClauseKind::VectorLength, BeginLoc, + LParenLoc, IntExpr, EndLoc) { + assert((!IntExpr || IntExpr->isInstantiationDependent() || + IntExpr->getType()->isIntegerType()) && + "Condition expression type not scalar/dependent"); +} + +OpenACCVectorLengthClause * +OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *IntExpr, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OpenACCVectorLengthClause), + alignof(OpenACCVectorLengthClause)); + return new (Mem) + OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -98,3 +140,13 @@ void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) { if (const Expr *CondExpr = C.getConditionExpr()) OS << "(" << CondExpr << ")"; } + +void OpenACCClausePrinter::VisitNumWorkersClause( + const OpenACCNumWorkersClause &C) { + OS << "num_workers(" << C.getIntExpr() << ")"; +} + +void OpenACCClausePrinter::VisitVectorLengthClause( + const OpenACCVectorLengthClause &C) { + OS << "vector_length(" << C.getIntExpr() << ")"; +} diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index a3b7431f7ffd6dc134cc4a58f9ec78b0498fca67..d9bf62c2bbb04a56afeac66aa5ed43fec9319f72 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2458,6 +2458,11 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) { } static bool isMsLayout(const ASTContext &Context) { + // Check if it's CUDA device compilation; ensure layout consistency with host. + if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice && + Context.getAuxTargetInfo()) + return Context.getAuxTargetInfo()->getCXXABI().isMicrosoft(); + return Context.getTargetInfo().getCXXABI().isMicrosoft(); } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index b26d804c6f079b2bae33c6418a7b29c1fea7d427..8138ae3a244a8baba6be68dac233308cd36fc46d 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2496,6 +2496,19 @@ void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) { if (Clause.hasConditionExpr()) Profiler.VisitStmt(Clause.getConditionExpr()); } + +void OpenACCClauseProfiler::VisitNumWorkersClause( + const OpenACCNumWorkersClause &Clause) { + assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr"); + Profiler.VisitStmt(Clause.getIntExpr()); +} + +void OpenACCClauseProfiler::VisitVectorLengthClause( + const OpenACCVectorLengthClause &Clause) { + assert(Clause.hasIntExpr() && + "vector_length clause requires a valid int expr"); + Profiler.VisitStmt(Clause.getIntExpr()); +} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index ff5b3df2d6dfac4d01a5e1cb9b4f24564b9984d9..e5a8b285715b3096c45dd9cbf5211d7125108fce 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -399,6 +399,8 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { break; case OpenACCClauseKind::If: case OpenACCClauseKind::Self: + case OpenACCClauseKind::NumWorkers: + case OpenACCClauseKind::VectorLength: // The condition expression will be printed as a part of the 'children', // but print 'clause' here so it is clear what is happening from the dump. OS << " clause"; diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp index 75188aef4d1a43664ae8aa555e1025b987e22757..6f179c1403b6f58700366d1c6e242ebfaf855c7f 100644 --- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp @@ -80,11 +80,12 @@ bool containsSameFields(const FieldSet &Fields, } /// Returns the fields of a `RecordDecl` that are initialized by an -/// `InitListExpr`, in the order in which they appear in -/// `InitListExpr::inits()`. -/// `Init->getType()` must be a record type. +/// `InitListExpr` or `CXXParenListInitExpr`, in the order in which they appear +/// in `InitListExpr::inits()` / `CXXParenListInitExpr::getInitExprs()`. +/// `InitList->getType()` must be a record type. +template static std::vector -getFieldsForInitListExpr(const InitListExpr *InitList) { +getFieldsForInitListExpr(const InitListT *InitList) { const RecordDecl *RD = InitList->getType()->getAsRecordDecl(); assert(RD != nullptr); @@ -101,23 +102,33 @@ getFieldsForInitListExpr(const InitListExpr *InitList) { // fields to avoid mapping inits to the wrongs fields. llvm::copy_if( RD->fields(), std::back_inserter(Fields), - [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); }); + [](const FieldDecl *Field) { return !Field->isUnnamedBitField(); }); return Fields; } -RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) { - auto *RD = InitList->getType()->getAsCXXRecordDecl(); - assert(RD != nullptr); +RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) + : RecordInitListHelper(InitList->getType(), + getFieldsForInitListExpr(InitList), + InitList->inits()) {} + +RecordInitListHelper::RecordInitListHelper( + const CXXParenListInitExpr *ParenInitList) + : RecordInitListHelper(ParenInitList->getType(), + getFieldsForInitListExpr(ParenInitList), + ParenInitList->getInitExprs()) {} - std::vector Fields = getFieldsForInitListExpr(InitList); - ArrayRef Inits = InitList->inits(); +RecordInitListHelper::RecordInitListHelper( + QualType Ty, std::vector Fields, + ArrayRef Inits) { + auto *RD = Ty->getAsCXXRecordDecl(); + assert(RD != nullptr); // Unions initialized with an empty initializer list need special treatment. // For structs/classes initialized with an empty initializer list, Clang // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions, // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves. SmallVector InitsForUnion; - if (InitList->getType()->isUnionType() && Inits.empty()) { + if (Ty->isUnionType() && Inits.empty()) { assert(Fields.size() == 1); ImplicitValueInitForUnion.emplace(Fields.front()->getType()); InitsForUnion.push_back(&*ImplicitValueInitForUnion); @@ -217,6 +228,10 @@ static void getReferencedDecls(const Stmt &S, ReferencedDecls &Referenced) { if (InitList->getType()->isRecordType()) for (const auto *FD : getFieldsForInitListExpr(InitList)) Referenced.Fields.insert(FD); + } else if (auto *ParenInitList = dyn_cast(&S)) { + if (ParenInitList->getType()->isRecordType()) + for (const auto *FD : getFieldsForInitListExpr(ParenInitList)) + Referenced.Fields.insert(FD); } } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 3f1600d9ac5d8724494bc35ce9436160a5269d28..05395e07a7a68cc035a7ca281d21cfe1b05e0e9e 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -80,7 +81,6 @@ static bool equateUnknownValues(Value::Kind K) { switch (K) { case Value::Kind::Integer: case Value::Kind::Pointer: - case Value::Kind::Record: return true; default: return false; @@ -145,25 +145,7 @@ static Value *joinDistinctValues(QualType Type, Value &Val1, return &A.makeBoolValue(JoinedVal); } - Value *JoinedVal = nullptr; - if (auto *RecordVal1 = dyn_cast(&Val1)) { - auto *RecordVal2 = cast(&Val2); - - if (&RecordVal1->getLoc() == &RecordVal2->getLoc()) - // `RecordVal1` and `RecordVal2` may have different properties associated - // with them. Create a new `RecordValue` with the same location but - // without any properties so that we soundly approximate both values. If a - // particular analysis needs to join properties, it should do so in - // `DataflowAnalysis::join()`. - JoinedVal = &JoinedEnv.create(RecordVal1->getLoc()); - else - // If the locations for the two records are different, need to create a - // completely new value. - JoinedVal = JoinedEnv.createValue(Type); - } else { - JoinedVal = JoinedEnv.createValue(Type); - } - + Value *JoinedVal = JoinedEnv.createValue(Type); if (JoinedVal) Model.join(Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv); @@ -401,6 +383,28 @@ public: return true; } + void + PropagateResultObjectToRecordInitList(const RecordInitListHelper &InitList, + RecordStorageLocation *Loc) { + for (auto [Base, Init] : InitList.base_inits()) { + assert(Base->getType().getCanonicalType() == + Init->getType().getCanonicalType()); + + // Storage location for the base class is the same as that of the + // derived class because we "flatten" the object hierarchy and put all + // fields in `RecordStorageLocation` of the derived class. + PropagateResultObject(Init, Loc); + } + + for (auto [Field, Init] : InitList.field_inits()) { + // Fields of non-record type are handled in + // `TransferVisitor::VisitInitListExpr()`. + if (Field->getType()->isRecordType()) + PropagateResultObject( + Init, cast(Loc->getChild(*Field))); + } + } + // Assigns `Loc` as the result object location of `E`, then propagates the // location to all lower-level prvalues that initialize the same object as // `E` (or one of its base classes or member variables). @@ -440,26 +444,14 @@ public: return; } - RecordInitListHelper InitListHelper(InitList); - - for (auto [Base, Init] : InitListHelper.base_inits()) { - assert(Base->getType().getCanonicalType() == - Init->getType().getCanonicalType()); - - // Storage location for the base class is the same as that of the - // derived class because we "flatten" the object hierarchy and put all - // fields in `RecordStorageLocation` of the derived class. - PropagateResultObject(Init, Loc); - } + PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList), + Loc); + return; + } - for (auto [Field, Init] : InitListHelper.field_inits()) { - // Fields of non-record type are handled in - // `TransferVisitor::VisitInitListExpr()`. - if (!Field->getType()->isRecordType()) - continue; - PropagateResultObject( - Init, cast(Loc->getChild(*Field))); - } + if (auto *ParenInitList = dyn_cast(E)) { + PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList), + Loc); return; } @@ -555,7 +547,6 @@ void Environment::initialize() { auto &ThisLoc = cast(createStorageLocation(ThisPointeeType)); setThisPointeeStorageLocation(ThisLoc); - refreshRecordValue(ThisLoc, *this); // Initialize fields of `*this` with values, but only if we're not // analyzing a constructor; after all, it's the constructor's job to do // this (and we want to be able to test that). @@ -619,8 +610,8 @@ Environment Environment::pushCall(const CallExpr *Call) const { if (const auto *MethodCall = dyn_cast(Call)) { if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) { if (!isa(Arg)) - Env.ThisPointeeLoc = - cast(getStorageLocation(*Arg)); + Env.ThisPointeeLoc = + cast(getStorageLocation(*Arg)); // Otherwise (when the argument is `this`), retain the current // environment's `ThisPointeeLoc`. } @@ -699,10 +690,6 @@ void Environment::popCall(const CXXConstructExpr *Call, // See also comment in `popCall(const CallExpr *, const Environment &)` above. this->LocToVal = std::move(CalleeEnv.LocToVal); this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); - - if (Value *Val = CalleeEnv.getValue(*CalleeEnv.ThisPointeeLoc)) { - setValue(*Call, *Val); - } } bool Environment::equivalentTo(const Environment &Other, @@ -926,24 +913,23 @@ void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc, } void Environment::setValue(const StorageLocation &Loc, Value &Val) { - assert(!isa(&Val) || &cast(&Val)->getLoc() == &Loc); - + // Records should not be associated with values. + assert(!isa(Loc)); LocToVal[&Loc] = &Val; } void Environment::setValue(const Expr &E, Value &Val) { const Expr &CanonE = ignoreCFGOmittedNodes(E); - if (auto *RecordVal = dyn_cast(&Val)) { - assert(&RecordVal->getLoc() == &getResultObjectLocation(CanonE)); - (void)RecordVal; - } - assert(CanonE.isPRValue()); + // Records should not be associated with values. + assert(!CanonE.getType()->isRecordType()); ExprToVal[&CanonE] = &Val; } Value *Environment::getValue(const StorageLocation &Loc) const { + // Records should not be associated with values. + assert(!isa(Loc)); return LocToVal.lookup(&Loc); } @@ -955,6 +941,9 @@ Value *Environment::getValue(const ValueDecl &D) const { } Value *Environment::getValue(const Expr &E) const { + // Records should not be associated with values. + assert(!E.getType()->isRecordType()); + if (E.isPRValue()) { auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E)); return It == ExprToVal.end() ? nullptr : It->second; @@ -983,6 +972,7 @@ Value *Environment::createValueUnlessSelfReferential( int &CreatedValuesCount) { assert(!Type.isNull()); assert(!Type->isReferenceType()); + assert(!Type->isRecordType()); // Allow unlimited fields at depth 1; only cap at deeper nesting levels. if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) || @@ -1011,15 +1001,6 @@ Value *Environment::createValueUnlessSelfReferential( return &arena().create(PointeeLoc); } - if (Type->isRecordType()) { - CreatedValuesCount++; - auto &Loc = cast(createStorageLocation(Type)); - initializeFieldsWithValues(Loc, Loc.getType(), Visited, Depth, - CreatedValuesCount); - - return &refreshRecordValue(Loc, *this); - } - return nullptr; } @@ -1029,20 +1010,23 @@ Environment::createLocAndMaybeValue(QualType Ty, int Depth, int &CreatedValuesCount) { if (!Visited.insert(Ty.getCanonicalType()).second) return createStorageLocation(Ty.getNonReferenceType()); - Value *Val = createValueUnlessSelfReferential( - Ty.getNonReferenceType(), Visited, Depth, CreatedValuesCount); - Visited.erase(Ty.getCanonicalType()); + auto EraseVisited = llvm::make_scope_exit( + [&Visited, Ty] { Visited.erase(Ty.getCanonicalType()); }); Ty = Ty.getNonReferenceType(); - if (Val == nullptr) - return createStorageLocation(Ty); - - if (Ty->isRecordType()) - return cast(Val)->getLoc(); + if (Ty->isRecordType()) { + auto &Loc = cast(createStorageLocation(Ty)); + initializeFieldsWithValues(Loc, Ty, Visited, Depth, CreatedValuesCount); + return Loc; + } StorageLocation &Loc = createStorageLocation(Ty); - setValue(Loc, *Val); + + if (Value *Val = createValueUnlessSelfReferential(Ty, Visited, Depth, + CreatedValuesCount)) + setValue(Loc, *Val); + return Loc; } @@ -1054,10 +1038,11 @@ void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc, auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) { if (FieldType->isRecordType()) { auto &FieldRecordLoc = cast(FieldLoc); - setValue(FieldRecordLoc, create(FieldRecordLoc)); initializeFieldsWithValues(FieldRecordLoc, FieldRecordLoc.getType(), Visited, Depth + 1, CreatedValuesCount); } else { + if (getValue(FieldLoc) != nullptr) + return; if (!Visited.insert(FieldType.getCanonicalType()).second) return; if (Value *Val = createValueUnlessSelfReferential( @@ -1098,7 +1083,7 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D, // be null. if (InitExpr) { if (auto *InitExprLoc = getStorageLocation(*InitExpr)) - return *InitExprLoc; + return *InitExprLoc; } // Even though we have an initializer, we might not get an @@ -1115,7 +1100,6 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D, auto &RecordLoc = cast(Loc); if (!InitExpr) initializeFieldsWithValues(RecordLoc); - refreshRecordValue(RecordLoc, *this); } else { Value *Val = nullptr; if (InitExpr) @@ -1207,9 +1191,7 @@ void Environment::dump(raw_ostream &OS) const { DACtx->dumpFlowCondition(FlowConditionToken, OS); } -void Environment::dump() const { - dump(llvm::dbgs()); -} +void Environment::dump() const { dump(llvm::dbgs()); } Environment::PrValueToResultObject Environment::buildResultObjectMap( DataflowAnalysisContext *DACtx, const FunctionDecl *FuncDecl, @@ -1254,25 +1236,5 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, return Env.get(*Base); } -RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) { - auto &NewVal = Env.create(Loc); - Env.setValue(Loc, NewVal); - return NewVal; -} - -RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) { - assert(Expr.getType()->isRecordType()); - - if (Expr.isPRValue()) - refreshRecordValue(Env.getResultObjectLocation(Expr), Env); - - if (auto *Loc = Env.get(Expr)) - refreshRecordValue(*Loc, Env); - - auto &NewVal = *cast(Env.createValue(Expr.getType())); - Env.setStorageLocation(Expr, NewVal.getLoc()); - return NewVal; -} - } // namespace dataflow } // namespace clang diff --git a/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp b/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp index 573c4b1d474bf474a0fe699222927de0bdf57eb9..d40aab7a7f10359e3bed23793d7298294f1ca00c 100644 --- a/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp +++ b/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp @@ -28,8 +28,6 @@ llvm::StringRef debugString(Value::Kind Kind) { return "Integer"; case Value::Kind::Pointer: return "Pointer"; - case Value::Kind::Record: - return "Record"; case Value::Kind::AtomicBool: return "AtomicBool"; case Value::Kind::TopBool: diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp index 397a8d87e114d7a90214f4bad99fb307ee605d3b..a36cb41a63dfb152527e01f163e47b2f662ba7c6 100644 --- a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp +++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp @@ -95,7 +95,6 @@ public: switch (V.getKind()) { case Value::Kind::Integer: - case Value::Kind::Record: case Value::Kind::TopBool: case Value::Kind::AtomicBool: case Value::Kind::FormulaBool: @@ -126,8 +125,9 @@ public: return; JOS.attribute("type", L.getType().getAsString()); - if (auto *V = Env.getValue(L)) - dump(*V); + if (!L.getType()->isRecordType()) + if (auto *V = Env.getValue(L)) + dump(*V); if (auto *RLoc = dyn_cast(&L)) { for (const auto &Child : RLoc->children()) @@ -281,9 +281,10 @@ public: Iters.back().Block->Elements[ElementIndex - 1].getAs(); if (const Expr *E = S ? llvm::dyn_cast(S->getStmt()) : nullptr) { if (E->isPRValue()) { - if (auto *V = State.Env.getValue(*E)) - JOS.attributeObject( - "value", [&] { ModelDumper(JOS, State.Env).dump(*V); }); + if (!E->getType()->isRecordType()) + if (auto *V = State.Env.getValue(*E)) + JOS.attributeObject( + "value", [&] { ModelDumper(JOS, State.Env).dump(*V); }); } else { if (auto *Loc = State.Env.getStorageLocation(*E)) JOS.attributeObject( diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index cadb1ceb2d850733829a9d18e1a0ddef67e80946..0707aa662e4cc2756135742cb17e4a2509ff3173 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -339,17 +339,6 @@ void setHasValue(RecordStorageLocation &OptionalLoc, BoolValue &HasValueVal, Env.setValue(locForHasValue(OptionalLoc), HasValueVal); } -/// Creates a symbolic value for an `optional` value at an existing storage -/// location. Uses `HasValueVal` as the symbolic value of the "has_value" -/// property. -RecordValue &createOptionalValue(RecordStorageLocation &Loc, - BoolValue &HasValueVal, Environment &Env) { - auto &OptionalVal = Env.create(Loc); - Env.setValue(Loc, OptionalVal); - setHasValue(Loc, HasValueVal, Env); - return OptionalVal; -} - /// Returns the symbolic value that represents the "has_value" property of the /// optional at `OptionalLoc`. Returns null if `OptionalLoc` is null. BoolValue *getHasValue(Environment &Env, RecordStorageLocation *OptionalLoc) { @@ -413,9 +402,8 @@ void transferArrowOpCall(const Expr *UnwrapExpr, const Expr *ObjectExpr, void transferMakeOptionalCall(const CallExpr *E, const MatchFinder::MatchResult &, LatticeTransferState &State) { - State.Env.setValue( - *E, createOptionalValue(State.Env.getResultObjectLocation(*E), - State.Env.getBoolLiteralValue(true), State.Env)); + setHasValue(State.Env.getResultObjectLocation(*E), + State.Env.getBoolLiteralValue(true), State.Env); } void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr, @@ -483,9 +471,6 @@ void transferValueOrNotEqX(const Expr *ComparisonExpr, void transferCallReturningOptional(const CallExpr *E, const MatchFinder::MatchResult &Result, LatticeTransferState &State) { - if (State.Env.getValue(*E) != nullptr) - return; - RecordStorageLocation *Loc = nullptr; if (E->isPRValue()) { Loc = &State.Env.getResultObjectLocation(*E); @@ -497,16 +482,16 @@ void transferCallReturningOptional(const CallExpr *E, } } - RecordValue &Val = - createOptionalValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env); - if (E->isPRValue()) - State.Env.setValue(*E, Val); + if (State.Env.getValue(locForHasValue(*Loc)) != nullptr) + return; + + setHasValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env); } void constructOptionalValue(const Expr &E, Environment &Env, BoolValue &HasValueVal) { RecordStorageLocation &Loc = Env.getResultObjectLocation(E); - Env.setValue(E, createOptionalValue(Loc, HasValueVal, Env)); + setHasValue(Loc, HasValueVal, Env); } /// Returns a symbolic value for the "has_value" property of an `optional` @@ -555,7 +540,7 @@ void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal, assert(E->getNumArgs() > 0); if (auto *Loc = State.Env.get(*E->getArg(0))) { - createOptionalValue(*Loc, HasValueVal, State.Env); + setHasValue(*Loc, HasValueVal, State.Env); // Assign a storage location for the whole expression. State.Env.setStorageLocation(*E, *Loc); @@ -587,11 +572,11 @@ void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2, if (Loc1 == nullptr) { if (Loc2 != nullptr) - createOptionalValue(*Loc2, Env.makeAtomicBoolValue(), Env); + setHasValue(*Loc2, Env.makeAtomicBoolValue(), Env); return; } if (Loc2 == nullptr) { - createOptionalValue(*Loc1, Env.makeAtomicBoolValue(), Env); + setHasValue(*Loc1, Env.makeAtomicBoolValue(), Env); return; } @@ -609,8 +594,8 @@ void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2, if (BoolVal2 == nullptr) BoolVal2 = &Env.makeAtomicBoolValue(); - createOptionalValue(*Loc1, *BoolVal2, Env); - createOptionalValue(*Loc2, *BoolVal1, Env); + setHasValue(*Loc1, *BoolVal2, Env); + setHasValue(*Loc2, *BoolVal1, Env); } void transferSwapCall(const CXXMemberCallExpr *E, @@ -806,8 +791,7 @@ auto buildTransferMatchSwitch() { LatticeTransferState &State) { if (RecordStorageLocation *Loc = getImplicitObjectLocation(*E, State.Env)) { - createOptionalValue(*Loc, State.Env.getBoolLiteralValue(true), - State.Env); + setHasValue(*Loc, State.Env.getBoolLiteralValue(true), State.Env); } }) @@ -818,8 +802,8 @@ auto buildTransferMatchSwitch() { LatticeTransferState &State) { if (RecordStorageLocation *Loc = getImplicitObjectLocation(*E, State.Env)) { - createOptionalValue(*Loc, State.Env.getBoolLiteralValue(false), - State.Env); + setHasValue(*Loc, State.Env.getBoolLiteralValue(false), + State.Env); } }) diff --git a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp index 2f0b0e5c5640c342710762b5794e186ae72d8f12..b8401230a83d4370b2ee47e42e2f64913bd7673d 100644 --- a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp @@ -83,9 +83,6 @@ void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, copySyntheticField(SrcFieldLoc->getType(), *SrcFieldLoc, Dst.getSyntheticField(Name), Env); } - - RecordValue *DstVal = &Env.create(Dst); - Env.setValue(Dst, *DstVal); } bool recordsEqual(const RecordStorageLocation &Loc1, const Environment &Env1, diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 1e034771014eaaa760a1ca516f5fa56ad6fecf1d..2771c8b2e37ebb7e114f60de6b2ea47370504828 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -96,6 +96,8 @@ static Value *maybeUnpackLValueExpr(const Expr &E, Environment &Env) { } static void propagateValue(const Expr &From, const Expr &To, Environment &Env) { + if (From.getType()->isRecordType()) + return; if (auto *Val = Env.getValue(From)) Env.setValue(To, *Val); } @@ -403,6 +405,9 @@ public: return; if (Ret->isPRValue()) { + if (Ret->getType()->isRecordType()) + return; + auto *Val = Env.getValue(*Ret); if (Val == nullptr) return; @@ -457,15 +462,9 @@ public: assert(ArgExpr != nullptr); propagateValueOrStorageLocation(*ArgExpr, *S, Env); - // If this is a prvalue of record type, we consider it to be an "original - // record constructor", which we always require to have a `RecordValue`. - // So make sure we have a value if we didn't propagate one above. if (S->isPRValue() && S->getType()->isRecordType()) { - if (Env.getValue(*S) == nullptr) { - auto &Loc = Env.getResultObjectLocation(*S); - Env.initializeFieldsWithValues(Loc); - refreshRecordValue(Loc, Env); - } + auto &Loc = Env.getResultObjectLocation(*S); + Env.initializeFieldsWithValues(Loc); } } @@ -495,7 +494,6 @@ public: } RecordStorageLocation &Loc = Env.getResultObjectLocation(*S); - Env.setValue(*S, refreshRecordValue(Loc, Env)); if (ConstructorDecl->isCopyOrMoveConstructor()) { // It is permissible for a copy/move constructor to have additional @@ -542,8 +540,7 @@ public: RecordStorageLocation *LocSrc = nullptr; if (Arg1->isPRValue()) { - if (auto *Val = Env.get(*Arg1)) - LocSrc = &Val->getLoc(); + LocSrc = &Env.getResultObjectLocation(*Arg1); } else { LocSrc = Env.get(*Arg1); } @@ -575,15 +572,6 @@ public: propagateValue(*RBO->getSemanticForm(), *RBO, Env); } - void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { - if (S->getCastKind() == CK_ConstructorConversion) { - const Expr *SubExpr = S->getSubExpr(); - assert(SubExpr != nullptr); - - propagateValue(*SubExpr, *S, Env); - } - } - void VisitCallExpr(const CallExpr *S) { // Of clang's builtins, only `__builtin_expect` is handled explicitly, since // others (like trap, debugtrap, and unreachable) are handled by CFG @@ -613,12 +601,10 @@ public: // If this call produces a prvalue of record type, initialize its fields // with values. - if (S->getType()->isRecordType() && S->isPRValue()) - if (Env.getValue(*S) == nullptr) { - RecordStorageLocation &Loc = Env.getResultObjectLocation(*S); - Env.initializeFieldsWithValues(Loc); - Env.setValue(*S, refreshRecordValue(Loc, Env)); - } + if (S->getType()->isRecordType() && S->isPRValue()) { + RecordStorageLocation &Loc = Env.getResultObjectLocation(*S); + Env.initializeFieldsWithValues(Loc); + } } } @@ -626,18 +612,16 @@ public: const Expr *SubExpr = S->getSubExpr(); assert(SubExpr != nullptr); - Value *SubExprVal = Env.getValue(*SubExpr); - if (SubExprVal == nullptr) - return; + StorageLocation &Loc = Env.createStorageLocation(*S); + Env.setStorageLocation(*S, Loc); - if (RecordValue *RecordVal = dyn_cast(SubExprVal)) { - Env.setStorageLocation(*S, RecordVal->getLoc()); + if (SubExpr->getType()->isRecordType()) + // Nothing else left to do -- we initialized the record when transferring + // `SubExpr`. return; - } - StorageLocation &Loc = Env.createStorageLocation(*S); - Env.setValue(Loc, *SubExprVal); - Env.setStorageLocation(*S, Loc); + if (Value *SubExprVal = Env.getValue(*SubExpr)) + Env.setValue(Loc, *SubExprVal); } void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) { @@ -683,15 +667,11 @@ public: return; } - // In case the initializer list is transparent, we just need to propagate - // the value that it contains. - if (S->isSemanticForm() && S->isTransparent()) { - propagateValue(*S->getInit(0), *S, Env); + // If the initializer list is transparent, there's nothing to do. + if (S->isSemanticForm() && S->isTransparent()) return; - } RecordStorageLocation &Loc = Env.getResultObjectLocation(*S); - Env.setValue(*S, refreshRecordValue(Loc, Env)); // Initialization of base classes and fields of record type happens when we // visit the nested `CXXConstructExpr` or `InitListExpr` for that base class diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 1b73c5d6830161070d66fa4c76614e4ab90d82a1..71d5c1a6c4f4a36fc818474c57bb568108b354d4 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -367,11 +367,11 @@ builtinTransferInitializer(const CFGInitializer &Elt, return; ParentLoc->setChild(*Member, InitExprLoc); - } else if (auto *InitExprVal = Env.getValue(*InitExpr)) { - assert(MemberLoc != nullptr); // Record-type initializers construct themselves directly into the result // object, so there is no need to handle them here. - if (!Member->getType()->isRecordType()) + } else if (!Member->getType()->isRecordType()) { + assert(MemberLoc != nullptr); + if (auto *InitExprVal = Env.getValue(*InitExpr)) Env.setValue(*MemberLoc, *InitExprVal); } } diff --git a/clang/lib/Analysis/FlowSensitive/Value.cpp b/clang/lib/Analysis/FlowSensitive/Value.cpp index 7fad6deb0e918fa4a5b1e5a5fed5b4dec9bed3ad..d70e5a82ea2327e8d6f02bcf352a703426647509 100644 --- a/clang/lib/Analysis/FlowSensitive/Value.cpp +++ b/clang/lib/Analysis/FlowSensitive/Value.cpp @@ -46,8 +46,6 @@ raw_ostream &operator<<(raw_ostream &OS, const Value &Val) { return OS << "Integer(@" << &Val << ")"; case Value::Kind::Pointer: return OS << "Pointer(" << &cast(Val).getPointeeLoc() << ")"; - case Value::Kind::Record: - return OS << "Record(" << &cast(Val).getLoc() << ")"; case Value::Kind::TopBool: return OS << "TopBool(" << cast(Val).getAtom() << ")"; case Value::Kind::AtomicBool: diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index e9111ded64eb1f8b46969bd5b1986f1f16e1839e..bf2f7306186507eb825bde3f974b71c3bf01fb09 100644 --- a/clang/lib/Analysis/UninitializedValues.cpp +++ b/clang/lib/Analysis/UninitializedValues.cpp @@ -44,7 +44,7 @@ static bool recordIsNotEmpty(const RecordDecl *RD) { // We consider a record decl to be empty if it contains only unnamed bit- // fields, zero-width fields, and fields of empty record type. for (const auto *FD : RD->fields()) { - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) continue; if (FD->isZeroSize(FD->getASTContext())) continue; diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 3e34d82cb399ba05f880cc7fd470cfac0af08a8d..eb627a3c043bc567e6dd82501182e0c573bbfa10 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -157,7 +157,7 @@ llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF, llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32( CGF.Builder.getInt8Ty(), Ptr, Align.getQuantity() - 1); return CGF.Builder.CreateIntrinsic( - llvm::Intrinsic::ptrmask, {CGF.AllocaInt8PtrTy, CGF.IntPtrTy}, + llvm::Intrinsic::ptrmask, {Ptr->getType(), CGF.IntPtrTy}, {RoundUp, llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())}, nullptr, Ptr->getName() + ".aligned"); } @@ -247,7 +247,7 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays, bool AsIfNoUniqueAddr) { - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) return true; QualType FT = FD->getType(); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3f5463a9a70e9d81a9da46e76bebe8955f9b3073..6c33cc17621f8961ae4cbfb7c3500a9f67e7ed0d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3665,7 +3665,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset, for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) { const FieldDecl *F = *I; - if (F->isUnnamedBitfield() || F->isZeroLengthBitField(Context) || + if (F->isUnnamedBitField() || F->isZeroLengthBitField(Context) || F->getType()->isIncompleteArrayType()) continue; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 8c284c332171a1bbdd9a3af14692e7de5ac81ec2..539ded5cca5e1b406df7b1c860501d50620b686a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1313,6 +1313,44 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, return DBuilder.createPointerType(EltTy, Size); } +static llvm::SmallVector +GetTemplateArgs(const TemplateDecl *TD, const TemplateSpecializationType *Ty) { + assert(Ty->isTypeAlias()); + // TemplateSpecializationType doesn't know if its template args are + // being substituted into a parameter pack. We can find out if that's + // the case now by inspecting the TypeAliasTemplateDecl template + // parameters. Insert Ty's template args into SpecArgs, bundling args + // passed to a parameter pack into a TemplateArgument::Pack. It also + // doesn't know the value of any defaulted args, so collect those now + // too. + SmallVector SpecArgs; + ArrayRef SubstArgs = Ty->template_arguments(); + for (const NamedDecl *Param : TD->getTemplateParameters()->asArray()) { + // If Param is a parameter pack, pack the remaining arguments. + if (Param->isParameterPack()) { + SpecArgs.push_back(TemplateArgument(SubstArgs)); + break; + } + + // Skip defaulted args. + // FIXME: Ideally, we wouldn't do this. We can read the default values + // for each parameter. However, defaulted arguments which are dependent + // values or dependent types can't (easily?) be resolved here. + if (SubstArgs.empty()) { + // If SubstArgs is now empty (we're taking from it each iteration) and + // this template parameter isn't a pack, then that should mean we're + // using default values for the remaining template parameters (after + // which there may be an empty pack too which we will ignore). + break; + } + + // Take the next argument. + SpecArgs.push_back(SubstArgs.front()); + SubstArgs = SubstArgs.drop_front(); + } + return SpecArgs; +} + llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, llvm::DIFile *Unit) { assert(Ty->isTypeAlias()); @@ -1332,6 +1370,31 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, auto PP = getPrintingPolicy(); Ty->getTemplateName().print(OS, PP, TemplateName::Qualified::None); + SourceLocation Loc = AliasDecl->getLocation(); + + if (CGM.getCodeGenOpts().DebugTemplateAlias) { + auto ArgVector = ::GetTemplateArgs(TD, Ty); + TemplateArgs Args = {TD->getTemplateParameters(), ArgVector}; + + // FIXME: Respect DebugTemplateNameKind::Mangled, e.g. by using GetName. + // Note we can't use GetName without additional work: TypeAliasTemplateDecl + // doesn't have instantiation information, so + // TypeAliasTemplateDecl::getNameForDiagnostic wouldn't have access to the + // template args. + std::string Name; + llvm::raw_string_ostream OS(Name); + TD->getNameForDiagnostic(OS, PP, /*Qualified=*/false); + if (CGM.getCodeGenOpts().getDebugSimpleTemplateNames() != + llvm::codegenoptions::DebugTemplateNamesKind::Simple || + !HasReconstitutableArgs(Args.Args)) + printTemplateArgumentList(OS, Args.Args, PP); + + llvm::DIDerivedType *AliasTy = DBuilder.createTemplateAlias( + Src, Name, getOrCreateFile(Loc), getLineNumber(Loc), + getDeclContextDescriptor(AliasDecl), CollectTemplateParams(Args, Unit)); + return AliasTy; + } + // Disable PrintCanonicalTypes here because we want // the DW_AT_name to benefit from the TypePrinter's ability // to skip defaulted template arguments. @@ -1343,8 +1406,6 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, PP.PrintCanonicalTypes = false; printTemplateArgumentList(OS, Ty->template_arguments(), PP, TD->getTemplateParameters()); - - SourceLocation Loc = AliasDecl->getLocation(); return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc), getLineNumber(Loc), getDeclContextDescriptor(AliasDecl)); @@ -5363,6 +5424,54 @@ static bool IsReconstitutableType(QualType QT) { return T.Reconstitutable; } +bool CGDebugInfo::HasReconstitutableArgs( + ArrayRef Args) const { + return llvm::all_of(Args, [&](const TemplateArgument &TA) { + switch (TA.getKind()) { + case TemplateArgument::Template: + // Easy to reconstitute - the value of the parameter in the debug + // info is the string name of the template. The template name + // itself won't benefit from any name rebuilding, but that's a + // representational limitation - maybe DWARF could be + // changed/improved to use some more structural representation. + return true; + case TemplateArgument::Declaration: + // Reference and pointer non-type template parameters point to + // variables, functions, etc and their value is, at best (for + // variables) represented as an address - not a reference to the + // DWARF describing the variable/function/etc. This makes it hard, + // possibly impossible to rebuild the original name - looking up + // the address in the executable file's symbol table would be + // needed. + return false; + case TemplateArgument::NullPtr: + // These could be rebuilt, but figured they're close enough to the + // declaration case, and not worth rebuilding. + return false; + case TemplateArgument::Pack: + // A pack is invalid if any of the elements of the pack are + // invalid. + return HasReconstitutableArgs(TA.getPackAsArray()); + case TemplateArgument::Integral: + // Larger integers get encoded as DWARF blocks which are a bit + // harder to parse back into a large integer, etc - so punting on + // this for now. Re-parsing the integers back into APInt is + // probably feasible some day. + return TA.getAsIntegral().getBitWidth() <= 64 && + IsReconstitutableType(TA.getIntegralType()); + case TemplateArgument::StructuralValue: + return false; + case TemplateArgument::Type: + return IsReconstitutableType(TA.getAsType()); + case TemplateArgument::Expression: + return IsReconstitutableType(TA.getAsExpr()->getType()); + default: + llvm_unreachable("Other, unresolved, template arguments should " + "not be seen here"); + } + }); +} + std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { std::string Name; llvm::raw_string_ostream OS(Name); @@ -5389,49 +5498,7 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { } else if (auto *VD = dyn_cast(ND)) { Args = GetTemplateArgs(VD); } - std::function)> HasReconstitutableArgs = - [&](ArrayRef Args) { - return llvm::all_of(Args, [&](const TemplateArgument &TA) { - switch (TA.getKind()) { - case TemplateArgument::Template: - // Easy to reconstitute - the value of the parameter in the debug - // info is the string name of the template. (so the template name - // itself won't benefit from any name rebuilding, but that's a - // representational limitation - maybe DWARF could be - // changed/improved to use some more structural representation) - return true; - case TemplateArgument::Declaration: - // Reference and pointer non-type template parameters point to - // variables, functions, etc and their value is, at best (for - // variables) represented as an address - not a reference to the - // DWARF describing the variable/function/etc. This makes it hard, - // possibly impossible to rebuild the original name - looking up the - // address in the executable file's symbol table would be needed. - return false; - case TemplateArgument::NullPtr: - // These could be rebuilt, but figured they're close enough to the - // declaration case, and not worth rebuilding. - return false; - case TemplateArgument::Pack: - // A pack is invalid if any of the elements of the pack are invalid. - return HasReconstitutableArgs(TA.getPackAsArray()); - case TemplateArgument::Integral: - // Larger integers get encoded as DWARF blocks which are a bit - // harder to parse back into a large integer, etc - so punting on - // this for now. Re-parsing the integers back into APInt is probably - // feasible some day. - return TA.getAsIntegral().getBitWidth() <= 64 && - IsReconstitutableType(TA.getIntegralType()); - case TemplateArgument::StructuralValue: - return false; - case TemplateArgument::Type: - return IsReconstitutableType(TA.getAsType()); - default: - llvm_unreachable("Other, unresolved, template arguments should " - "not be seen here"); - } - }); - }; + // A conversion operator presents complications/ambiguity if there's a // conversion to class template that is itself a template, eg: // template diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 7b60e94555d0608639789aacbb309843c1cf6fe4..d6db4d711366accf43100ef70628bbb9f2d345e5 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -626,7 +626,8 @@ private: llvm::DIType *WrappedType; }; - std::string GetName(const Decl*, bool Qualified = false) const; + bool HasReconstitutableArgs(ArrayRef Args) const; + std::string GetName(const Decl *, bool Qualified = false) const; /// Build up structure info for the byref. See \a BuildByRefType. BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD, diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index cf696a1c9f560ff20be45dd2b96e64c7e6f61929..931cb391342ea236224fbd9ba85a05edd356c09f 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4704,7 +4704,7 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec, for (auto *F : Rec->getDefinition()->fields()) { if (I == FieldIndex) break; - if (F->isUnnamedBitfield()) + if (F->isUnnamedBitField()) Skipped++; I++; } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 1b9287ea239347d334c2c7d52e2cc092e281aeb5..355fec42be4489389fa71aa73b948afbf9701069 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1755,7 +1755,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // Make sure that it's really an empty and not a failure of // semantic analysis. for (const auto *Field : record->fields()) - assert((Field->isUnnamedBitfield() || Field->isAnonymousStructOrUnion()) && "Only unnamed bitfields or ananymous class allowed"); + assert( + (Field->isUnnamedBitField() || Field->isAnonymousStructOrUnion()) && + "Only unnamed bitfields or ananymous class allowed"); #endif return; } @@ -1783,7 +1785,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( break; // Always skip anonymous bitfields. - if (field->isUnnamedBitfield()) + if (field->isUnnamedBitField()) continue; // We're done if we reach the end of the explicit initializers, we @@ -1988,7 +1990,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { if (Field->getType()->isIncompleteArrayType() || ILEElement == ILE->getNumInits()) break; - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; const Expr *E = ILE->getInit(ILEElement++); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index a4fb673284ceca6bde6cc331279a4c4b42b6e39d..673ccef84d67814dd27bdd54bcc168f28540ae92 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1235,7 +1235,7 @@ void CodeGenFunction::EmitNewArrayInitializer( if (auto *CXXRD = dyn_cast(RType->getDecl())) NumElements = CXXRD->getNumBases(); for (auto *Field : RType->getDecl()->fields()) - if (!Field->isUnnamedBitfield()) + if (!Field->isUnnamedBitField()) ++NumElements; // FIXME: Recurse into nested InitListExprs. if (ILE->getNumInits() == NumElements) diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 9f1b06eebf9ed089c4dc1d2cbce75a203ff951f9..c924660c5a91c8ca05303e86ed9576edd0eb57fe 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -706,7 +706,7 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) { continue; // Don't emit anonymous bitfields. - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; // Get the initializer. A struct can include fields without initializers, @@ -840,7 +840,7 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, continue; // Don't emit anonymous bitfields or zero-sized fields. - if (Field->isUnnamedBitfield() || Field->isZeroSize(CGM.getContext())) + if (Field->isUnnamedBitField() || Field->isZeroSize(CGM.getContext())) continue; // Emit the value of the initializer. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 1f18e0d5ba409a88b3e51b098219685d7a5fc8cb..c76052ff6280f98dab14f366f6952e24cbad7633 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -147,6 +147,15 @@ struct BinOpInfo { return UnOp->getSubExpr()->getType()->isFixedPointType(); return false; } + + /// Check if the RHS has a signed integer representation. + bool rhsHasSignedIntegerRepresentation() const { + if (const auto *BinOp = dyn_cast(E)) { + QualType RHSType = BinOp->getRHS()->getType(); + return RHSType->hasSignedIntegerRepresentation(); + } + return false; + } }; static bool MustVisitNullValue(const Expr *E) { @@ -782,7 +791,7 @@ public: void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops, llvm::Value *Zero,bool isDiv); // Common helper for getting how wide LHS of shift is. - static Value *GetMaximumShiftAmount(Value *LHS, Value *RHS); + static Value *GetMaximumShiftAmount(Value *LHS, Value *RHS, bool RHSIsSigned); // Used for shifting constraints for OpenCL, do mask for powers of 2, URem for // non powers of two. @@ -4344,7 +4353,8 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) { return Builder.CreateExactSDiv(diffInChars, divisor, "sub.ptr.div"); } -Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS) { +Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS, + bool RHSIsSigned) { llvm::IntegerType *Ty; if (llvm::VectorType *VT = dyn_cast(LHS->getType())) Ty = cast(VT->getElementType()); @@ -4355,7 +4365,9 @@ Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS) { // this in ConstantInt::get, this results in the value getting truncated. // Constrain the return value to be max(RHS) in this case. llvm::Type *RHSTy = RHS->getType(); - llvm::APInt RHSMax = llvm::APInt::getMaxValue(RHSTy->getScalarSizeInBits()); + llvm::APInt RHSMax = + RHSIsSigned ? llvm::APInt::getSignedMaxValue(RHSTy->getScalarSizeInBits()) + : llvm::APInt::getMaxValue(RHSTy->getScalarSizeInBits()); if (RHSMax.ult(Ty->getBitWidth())) return llvm::ConstantInt::get(RHSTy, RHSMax); return llvm::ConstantInt::get(RHSTy, Ty->getBitWidth() - 1); @@ -4370,7 +4382,7 @@ Value *ScalarExprEmitter::ConstrainShiftValue(Value *LHS, Value *RHS, Ty = cast(LHS->getType()); if (llvm::isPowerOf2_64(Ty->getBitWidth())) - return Builder.CreateAnd(RHS, GetMaximumShiftAmount(LHS, RHS), Name); + return Builder.CreateAnd(RHS, GetMaximumShiftAmount(LHS, RHS, false), Name); return Builder.CreateURem( RHS, llvm::ConstantInt::get(RHS->getType(), Ty->getBitWidth()), Name); @@ -4403,7 +4415,9 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { isa(Ops.LHS->getType())) { CodeGenFunction::SanitizerScope SanScope(&CGF); SmallVector, 2> Checks; - llvm::Value *WidthMinusOne = GetMaximumShiftAmount(Ops.LHS, Ops.RHS); + bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation(); + llvm::Value *WidthMinusOne = + GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned); llvm::Value *ValidExponent = Builder.CreateICmpULE(Ops.RHS, WidthMinusOne); if (SanitizeExponent) { @@ -4421,7 +4435,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { Builder.CreateCondBr(ValidExponent, CheckShiftBase, Cont); llvm::Value *PromotedWidthMinusOne = (RHS == Ops.RHS) ? WidthMinusOne - : GetMaximumShiftAmount(Ops.LHS, RHS); + : GetMaximumShiftAmount(Ops.LHS, RHS, RHSIsSigned); CGF.EmitBlock(CheckShiftBase); llvm::Value *BitsShiftedOff = Builder.CreateLShr( Ops.LHS, Builder.CreateSub(PromotedWidthMinusOne, RHS, "shl.zeros", @@ -4471,8 +4485,9 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) && isa(Ops.LHS->getType())) { CodeGenFunction::SanitizerScope SanScope(&CGF); - llvm::Value *Valid = - Builder.CreateICmpULE(Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS)); + bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation(); + llvm::Value *Valid = Builder.CreateICmpULE( + Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned)); EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::ShiftExponent), Ops); } diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 0d4800b90a2f26c67ba51fff219673fb5290a8e4..72d1471021ac02971f8d4da33e0ef149df12a501 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -673,6 +673,8 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, setPipelineDisabled(true); break; case LoopHintAttr::UnrollCount: + setUnrollState(LoopAttributes::Disable); + break; case LoopHintAttr::UnrollAndJamCount: case LoopHintAttr::VectorizeWidth: case LoopHintAttr::InterleaveCount: diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index da689ee6a13d7087ee019caccbd18911888ee33b..284421f494711e3c8c50479dad3a8bc8e4614b8e 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -414,7 +414,7 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { }); } for (FieldDecl *Field : RD->fields()) { - if (Field->isZeroSize(Context) || Field->isUnnamedBitfield()) + if (Field->isZeroSize(Context) || Field->isUnnamedBitField()) continue; QualType FieldQTy = Field->getType(); llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 71215da362d3d01a3c1fc622db29a4103fb44cff..64c39c5de351c7a2f2fffed3809ac75b482f79d3 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -2011,11 +2011,13 @@ struct CounterCoverageMappingBuilder Counter TrueCount = llvm::EnableSingleByteCoverage ? getRegionCounter(E->getTrueExpr()) : getRegionCounter(E); - - propagateCounts(ParentCount, E->getCond()); Counter OutCount; - if (!isa(E)) { + if (const auto *BCO = dyn_cast(E)) { + propagateCounts(ParentCount, BCO->getCommon()); + OutCount = TrueCount; + } else { + propagateCounts(ParentCount, E->getCond()); // The 'then' count applies to the area immediately after the condition. auto Gap = findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr())); @@ -2024,8 +2026,6 @@ struct CounterCoverageMappingBuilder extendRegion(E->getTrueExpr()); OutCount = propagateCounts(TrueCount, E->getTrueExpr()); - } else { - OutCount = TrueCount; } extendRegion(E->getFalseExpr()); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index f04db56db3357dd26364d4ce23fe0ecb6b7ccc1d..94cf0d86f9bed7256d20a2d7f0abc507608baa97 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2087,7 +2087,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, bool BitField = i->isBitField(); // Ignore padding bit-fields. - if (BitField && i->isUnnamedBitfield()) + if (BitField && i->isUnnamedBitField()) continue; // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger than @@ -2128,7 +2128,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, // structure to be passed in memory even if unaligned, and // therefore they can straddle an eightbyte. if (BitField) { - assert(!i->isUnnamedBitfield()); + assert(!i->isUnnamedBitField()); uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); uint64_t Size = i->getBitWidthValue(getContext()); diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 3f10888596a29a04d7dea3f1af0962be4c680b01..c1b350893b3744ae818aef707591eacec1e6904c 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -362,6 +362,30 @@ AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { return "/"; } +void AIX::AddOpenMPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + // Add OpenMP include paths if -fopenmp is specified. + if (DriverArgs.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + SmallString<128> PathOpenMP; + switch (getDriver().getOpenMPRuntime(DriverArgs)) { + case Driver::OMPRT_OMP: + PathOpenMP = GetHeaderSysroot(DriverArgs); + llvm::sys::path::append(PathOpenMP, "opt/IBM/openxlCSDK", "include", + "openmp"); + addSystemInclude(DriverArgs, CC1Args, PathOpenMP.str()); + break; + case Driver::OMPRT_IOMP5: + LLVM_FALLTHROUGH; + case Driver::OMPRT_GOMP: + LLVM_FALLTHROUGH; + case Driver::OMPRT_Unknown: + // Unknown / unsupported include paths. + break; + } + } +} + void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Return if -nostdinc is specified as a driver option. @@ -380,6 +404,11 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str())); } + // Add the include directory containing omp.h. This needs to be before + // adding the system include directory because other compilers put their + // omp.h in /usr/include. + AddOpenMPIncludeArgs(DriverArgs, CC1Args); + // Return if -nostdlibinc is specified as a driver option. if (DriverArgs.hasArg(options::OPT_nostdlibinc)) return; diff --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h index 755d87e07ec5003e69ca366ca67504a0c3a3776b..8f130f6b54547c9e73735ad3cc4353c53846f24d 100644 --- a/clang/lib/Driver/ToolChains/AIX.h +++ b/clang/lib/Driver/ToolChains/AIX.h @@ -105,6 +105,8 @@ protected: private: llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const; bool ParseInlineAsmUsingAsmParser; + void AddOpenMPIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; }; } // end namespace toolchains diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 096ed14f957046a3dc7f8c41d20c4aa837acf5b9..456ea74caadb009b01e87583aec0272e125d8195 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4632,6 +4632,21 @@ 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; + 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 + // asks for it we should let them have it (if the target supports it). + if (checkDebugInfoOption(DebugTemplateAlias, Args, D, TC)) { + const auto &Opt = DebugTemplateAlias->getOption(); + UseDebugTemplateAlias = Opt.matches(options::OPT_gtemplate_alias); + } + } + if (UseDebugTemplateAlias) + CmdArgs.push_back("-gtemplate-alias"); + if (const Arg *A = Args.getLastArg(options::OPT_gsrc_hash_EQ)) { StringRef v = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-gsrc-hash=" + v)); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index f10aa4dfaa9ddd9a9dde4679e8990240d63a1d44..b65b96db16bd79583dc6dd4857f27c111ee0fb88 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2116,8 +2116,12 @@ unsigned tools::getDwarfVersion(const ToolChain &TC, const llvm::opt::ArgList &Args) { unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args); if (const Arg *GDwarfN = getDwarfNArg(Args)) - if (int N = DwarfVersionNum(GDwarfN->getSpelling())) + if (int N = DwarfVersionNum(GDwarfN->getSpelling())) { DwarfVersion = N; + if (DwarfVersion == 5 && TC.getTriple().isOSAIX()) + TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) + << GDwarfN->getSpelling() << TC.getTriple().str(); + } if (DwarfVersion == 0) { DwarfVersion = TC.GetDefaultDwarfVersion(); assert(DwarfVersion && "toolchain default DWARF version must be nonzero"); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 628f70417866c38505cf01128d26ffbfa345b22b..a679683077ac949e38ce55dc388fe9256977535b 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2912,6 +2912,8 @@ private: return TT_UnaryOperator; if (PrevToken->is(TT_TypeName)) return TT_PointerOrReference; + if (PrevToken->isOneOf(tok::kw_new, tok::kw_delete) && Tok.is(tok::ampamp)) + return TT_BinaryOperator; const FormatToken *NextToken = Tok.getNextNonComment(); @@ -5595,12 +5597,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; if (Left.IsUnterminatedLiteral) return true; - // FIXME: Breaking after newlines seems useful in general. Turn this into an - // option and recognize more cases like endl etc, and break independent of - // what comes after operator lessless. - if (Right.is(tok::lessless) && Right.Next && - Right.Next->is(tok::string_literal) && Left.is(tok::string_literal) && - Left.TokenText.ends_with("\\n\"")) { + if (Right.is(tok::lessless) && Right.Next && Left.is(tok::string_literal) && + Right.Next->is(tok::string_literal)) { return true; } if (Right.is(TT_RequiresClause)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 1f1f5440ddd75faadabdf076943f8b4e031250e0..5531e938e0f4f4f9fa2e48f39caedfd21d1052b6 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1556,6 +1556,9 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, llvm::DICompileUnit::DebugNameTableKind::Default)) GenerateArg(Consumer, OPT_gpubnames); + if (Opts.DebugTemplateAlias) + GenerateArg(Consumer, OPT_gtemplate_alias); + auto TNK = Opts.getDebugSimpleTemplateNames(); if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) { if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple) @@ -1827,6 +1830,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.BinutilsVersion = std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ)); + Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias); + Opts.DebugNameTable = static_cast( Args.hasArg(OPT_ggnu_pubnames) ? llvm::DICompileUnit::DebugNameTableKind::GNU diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp index 737877329c9ce758ff159fff7e651cd69c951a54..744ea70cc24def6442cdd1c306ab43334daa6862 100644 --- a/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/clang/lib/Frontend/MultiplexConsumer.cpp @@ -20,6 +20,9 @@ using namespace clang; namespace clang { +class NamespaceDecl; +class TranslationUnitDecl; + MultiplexASTDeserializationListener::MultiplexASTDeserializationListener( const std::vector& L) : Listeners(L) { @@ -115,6 +118,11 @@ public: void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; void AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) override; + void EnteringModulePurview() override; + void AddedManglingNumber(const Decl *D, unsigned) override; + void AddedStaticLocalNumbers(const Decl *D, unsigned) override; + void AddedAnonymousNamespace(const TranslationUnitDecl *, + NamespaceDecl *AnonNamespace) override; private: std::vector Listeners; @@ -238,6 +246,27 @@ void MultiplexASTMutationListener::AddedAttributeToRecord( L->AddedAttributeToRecord(Attr, Record); } +void MultiplexASTMutationListener::EnteringModulePurview() { + for (auto *L : Listeners) + L->EnteringModulePurview(); +} + +void MultiplexASTMutationListener::AddedManglingNumber(const Decl *D, + unsigned Number) { + for (auto *L : Listeners) + L->AddedManglingNumber(D, Number); +} +void MultiplexASTMutationListener::AddedStaticLocalNumbers(const Decl *D, + unsigned Number) { + for (auto *L : Listeners) + L->AddedStaticLocalNumbers(D, Number); +} +void MultiplexASTMutationListener::AddedAnonymousNamespace( + const TranslationUnitDecl *TU, NamespaceDecl *AnonNamespace) { + for (auto *L : Listeners) + L->AddedAnonymousNamespace(TU, AnonNamespace); +} + } // end namespace clang MultiplexConsumer::MultiplexConsumer( diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp index 84d9b5892e88da14471d78a4ada28cd4f2a86012..216b5eb799cb348557b2b2af5a4bbb98831e585d 100644 --- a/clang/lib/InstallAPI/DylibVerifier.cpp +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -674,6 +674,11 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { return; } + if (Aliases.count({SymbolName.str(), SymCtx.Kind})) { + updateState(Result::Valid); + return; + } + // All checks at this point classify as some kind of violation. // The different verification modes dictate whether they are reported to the // user. @@ -973,5 +978,24 @@ bool DylibVerifier::verifyBinaryAttrs(const ArrayRef ProvidedTargets, return true; } +std::unique_ptr DylibVerifier::takeExports() { + for (const auto &[Alias, Base] : Aliases) { + TargetList Targets; + SymbolFlags Flags = SymbolFlags::None; + if (const Symbol *Sym = Exports->findSymbol(Base.second, Base.first)) { + Flags = Sym->getFlags(); + Targets = {Sym->targets().begin(), Sym->targets().end()}; + } + + Record R(Alias.first, RecordLinkage::Exported, Flags); + SymbolContext SymCtx; + SymCtx.SymbolName = Alias.first; + SymCtx.Kind = Alias.second; + addSymbol(&R, SymCtx, std::move(Targets)); + } + + return std::move(Exports); +} + } // namespace installapi } // namespace clang diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index cf31456b6950ac51de7c220c65d7f374c63ea781..b20e6efcebfd10fb944e1a1b5961aa681ed7d8aa 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -550,7 +550,8 @@ std::unique_ptr Interpreter::FindRuntimeInterface() { auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) { LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(), - Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); + Sema::LookupOrdinaryName, + RedeclarationKind::ForVisibleRedeclaration); S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl()); if (R.empty()) return false; diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp index c19cf6aa3156c9322fd70eb6a1967b5370abb6f3..45f6322b8461ed6fd32579cb346743a55a901f7c 100644 --- a/clang/lib/Interpreter/InterpreterUtils.cpp +++ b/clang/lib/Interpreter/InterpreterUtils.cpp @@ -72,7 +72,7 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name, const DeclContext *Within) { DeclarationName DName = &S.Context.Idents.get(Name); LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName, - Sema::ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); R.suppressDiagnostics(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 274ee7b10c178771e3748ac0b9b5adb2ee07e89c..5f26b5a9e46befd4069ff325d6a301079df5fafe 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -7660,8 +7660,21 @@ void Parser::ParseParameterDeclarationClause( // Parse a C++23 Explicit Object Parameter // We do that in all language modes to produce a better diagnostic. SourceLocation ThisLoc; - if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) + if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) { ThisLoc = ConsumeToken(); + // C++23 [dcl.fct]p6: + // An explicit-object-parameter-declaration is a parameter-declaration + // with a this specifier. An explicit-object-parameter-declaration + // shall appear only as the first parameter-declaration of a + // parameter-declaration-list of either: + // - a member-declarator that declares a member function, or + // - a lambda-declarator. + // + // The parameter-declaration-list of a requires-expression is not such + // a context. + if (DeclaratorCtx == DeclaratorContext::RequiresExpr) + Diag(ThisLoc, diag::err_requires_expr_explicit_object_parameter); + } ParseDeclarationSpecifiers(DS, /*TemplateInfo=*/ParsedTemplateInfo(), AS_none, DeclSpecContext::DSC_normal, diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 51fd64b2d01aa71ce45ee214a3ad51d5ff36b4b2..8e0e86824829333027896dfb1da42f0e33bf53a3 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -799,6 +799,11 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( ProhibitAttributes(PrefixAttrs); Decl *DeclFromDeclSpec = nullptr; + Scope *CurScope = getCurScope(); + if (CurScope) + CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope | + CurScope->getFlags()); + Decl *AD = ParseAliasDeclarationAfterDeclarator( TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec); return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 43d6105dcf31c43ee9c56621907e5c7cc192dba0..0d2ad980696fcc26e35d34bc1a0155dc9cde8298 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -3910,10 +3910,10 @@ ExprResult Parser::ParseTypeTrait() { SmallVector Args; do { // Parse the next type. - TypeResult Ty = - ParseTypeName(/*SourceRange=*/nullptr, - getLangOpts().CPlusPlus ? DeclaratorContext::TemplateArg - : DeclaratorContext::TypeName); + TypeResult Ty = ParseTypeName(/*SourceRange=*/nullptr, + getLangOpts().CPlusPlus + ? DeclaratorContext::TemplateTypeArg + : DeclaratorContext::TypeName); if (Ty.isInvalid()) { Parens.skipToEnd(); return ExprError(); @@ -3955,8 +3955,8 @@ ExprResult Parser::ParseArrayTypeTrait() { if (T.expectAndConsume()) return ExprError(); - TypeResult Ty = - ParseTypeName(/*SourceRange=*/nullptr, DeclaratorContext::TemplateArg); + TypeResult Ty = ParseTypeName(/*SourceRange=*/nullptr, + DeclaratorContext::TemplateTypeArg); if (Ty.isInvalid()) { SkipUntil(tok::comma, StopAtSemi); SkipUntil(tok::r_paren, StopAtSemi); diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 123be476e928eeb54e772eacb9e9577d2a18afaf..757417f75c9636e53444875dbc38c1f677ef1fc6 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -632,10 +632,16 @@ Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { return Clauses; } -ExprResult Parser::ParseOpenACCIntExpr() { - // FIXME: this is required to be an integer expression (or dependent), so we - // should ensure that is the case by passing this to SEMA here. - return getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); +ExprResult Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, + OpenACCClauseKind CK, + SourceLocation Loc) { + ExprResult ER = + getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + + if (!ER.isUsable()) + return ER; + + return getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()); } bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { @@ -739,7 +745,7 @@ bool Parser::ParseOpenACCSizeExprList() { /// [num:]int-expr /// dim:int-expr /// static:size-expr -bool Parser::ParseOpenACCGangArg() { +bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) && NextToken().is(tok::colon)) { @@ -753,7 +759,9 @@ bool Parser::ParseOpenACCGangArg() { NextToken().is(tok::colon)) { ConsumeToken(); ConsumeToken(); - return ParseOpenACCIntExpr().isInvalid(); + return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, + OpenACCClauseKind::Gang, GangLoc) + .isInvalid(); } if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) && @@ -763,11 +771,13 @@ bool Parser::ParseOpenACCGangArg() { // Fallthrough to the 'int-expr' handling for when 'num' is omitted. } // This is just the 'num' case where 'num' is optional. - return ParseOpenACCIntExpr().isInvalid(); + return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, + OpenACCClauseKind::Gang, GangLoc) + .isInvalid(); } -bool Parser::ParseOpenACCGangArgList() { - if (ParseOpenACCGangArg()) { +bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) { + if (ParseOpenACCGangArg(GangLoc)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); return false; @@ -776,7 +786,7 @@ bool Parser::ParseOpenACCGangArgList() { while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { ExpectAndConsume(tok::comma); - if (ParseOpenACCGangArg()) { + if (ParseOpenACCGangArg(GangLoc)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); return false; @@ -941,11 +951,19 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::VectorLength: { - ExprResult IntExpr = ParseOpenACCIntExpr(); + ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, + ClauseKind, ClauseLoc); if (IntExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); } + + // TODO OpenACC: as we implement the 'rest' of the above, this 'if' should + // be removed leaving just the 'setIntExprDetails'. + if (ClauseKind == OpenACCClauseKind::NumWorkers || + ClauseKind == OpenACCClauseKind::VectorLength) + ParsedClause.setIntExprDetails(IntExpr.get()); + break; } case OpenACCClauseKind::DType: @@ -998,7 +1016,8 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( ? OpenACCSpecialTokenKind::Length : OpenACCSpecialTokenKind::Num, ClauseKind); - ExprResult IntExpr = ParseOpenACCIntExpr(); + ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, + ClauseKind, ClauseLoc); if (IntExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); @@ -1014,13 +1033,14 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( break; } case OpenACCClauseKind::Gang: - if (ParseOpenACCGangArgList()) { + if (ParseOpenACCGangArgList(ClauseLoc)) { Parens.skipToEnd(); return OpenACCCanContinue(); } break; case OpenACCClauseKind::Wait: - if (ParseOpenACCWaitArgument()) { + if (ParseOpenACCWaitArgument(ClauseLoc, + /*IsDirective=*/false)) { Parens.skipToEnd(); return OpenACCCanContinue(); } @@ -1052,7 +1072,7 @@ ExprResult Parser::ParseOpenACCAsyncArgument() { /// In this section and throughout the specification, the term wait-argument /// means: /// [ devnum : int-expr : ] [ queues : ] async-argument-list -bool Parser::ParseOpenACCWaitArgument() { +bool Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) { // [devnum : int-expr : ] if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && NextToken().is(tok::colon)) { @@ -1061,7 +1081,11 @@ bool Parser::ParseOpenACCWaitArgument() { // Consume colon. ConsumeToken(); - ExprResult IntExpr = ParseOpenACCIntExpr(); + ExprResult IntExpr = ParseOpenACCIntExpr( + IsDirective ? OpenACCDirectiveKind::Wait + : OpenACCDirectiveKind::Invalid, + IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, + Loc); if (IntExpr.isInvalid()) return true; @@ -1245,7 +1269,7 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() { break; case OpenACCDirectiveKind::Wait: // OpenACC has an optional paren-wrapped 'wait-argument'. - if (ParseOpenACCWaitArgument()) + if (ParseOpenACCWaitArgument(StartLoc, /*IsDirective=*/true)) T.skipToEnd(); else T.consumeClose(); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 3979f75b6020dbba3d91ae2e747aac6bbcdf996a..cd0fab5fe31d3fc66928ccd079d380441cbd7ee6 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -1569,7 +1569,8 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { ConsumeToken(); // Consume the constant expression eof terminator. if (Arg2Error || R.isInvalid() || - Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) + Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(), + /*AllowZero=*/false)) return false; // Argument is a constant expression with an integer type. @@ -1594,7 +1595,8 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { ConsumeToken(); // Consume the constant expression eof terminator. if (R.isInvalid() || - Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) + Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(), + /*AllowZero=*/true)) return false; // Argument is a constant expression with an integer type. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 99b0a00083535eef22b69f442eb089c8dc5ffc7b..73e76e05a0d9d152ead9c13adeb0837060604553 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -622,7 +622,7 @@ struct BuiltinDumpStructGenerator { for (auto *D : RD->decls()) { auto *IFD = dyn_cast(D); auto *FD = IFD ? IFD->getAnonField() : dyn_cast(D); - if (!FD || FD->isUnnamedBitfield() || FD->isAnonymousStructOrUnion()) + if (!FD || FD->isUnnamedBitField() || FD->isAnonymousStructOrUnion()) continue; llvm::SmallString<20> Format = llvm::StringRef("%s%s %s "); @@ -3507,11 +3507,15 @@ bool Sema::ParseSVEImmChecks( static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { if (FD->hasAttr()) return ArmStreaming; - if (const auto *T = FD->getType()->getAs()) { - if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) - return ArmStreaming; - if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) - return ArmStreamingCompatible; + if (const Type *Ty = FD->getType().getTypePtrOrNull()) { + if (const auto *FPT = Ty->getAs()) { + if (FPT->getAArch64SMEAttributes() & + FunctionType::SME_PStateSMEnabledMask) + return ArmStreaming; + if (FPT->getAArch64SMEAttributes() & + FunctionType::SME_PStateSMCompatibleMask) + return ArmStreamingCompatible; + } } return ArmNonStreaming; } @@ -7949,7 +7953,6 @@ 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]) { @@ -7963,8 +7966,6 @@ 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); @@ -7985,23 +7986,6 @@ 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 = @@ -8010,7 +7994,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, CalleeArmZT0State != FunctionType::ARM_None) { bool CallerHasZAState = false; bool CallerHasZT0State = false; - if (CallerFD) { + if (const auto *CallerFD = dyn_cast(CurContext)) { auto *Attr = CallerFD->getAttr(); if (Attr && Attr->isNewZA()) CallerHasZAState = true; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 19abd5327b73aae1398f44aaafae8b99cf5d0527..af6b3f21f15a65878de26a9b376bd073beca5682 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5374,7 +5374,7 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, Scope *S, LookupResult R(SemaRef, Name, NameLoc, Owner->isRecord() ? Sema::LookupMemberName : Sema::LookupOrdinaryName, - Sema::ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); if (!SemaRef.LookupName(R, S)) return false; // Pick a representative declaration. @@ -6470,7 +6470,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, if (IsLinkageLookup) { Previous.clear(LookupRedeclarationWithLinkage); - Previous.setRedeclarationKind(ForExternalRedeclaration); + Previous.setRedeclarationKind( + RedeclarationKind::ForExternalRedeclaration); } LookupName(Previous, S, CreateBuiltins); @@ -8521,7 +8522,8 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { return; LookupResult R(*this, D->getDeclName(), D->getLocation(), - Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); + Sema::LookupOrdinaryName, + RedeclarationKind::ForVisibleRedeclaration); LookupName(R, S); if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R)) CheckShadow(D, ShadowedDecl, R); @@ -9161,7 +9163,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration( LookupResult Prev(SemaRef, Name, NewFD->getLocation(), IsLocalFriend ? Sema::LookupLocalFriendName : Sema::LookupOrdinaryName, - Sema::ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); NewFD->setInvalidDecl(); if (IsLocalFriend) @@ -12406,22 +12408,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } // Check if the function definition uses any AArch64 SME features without - // having the '+sme' feature enabled and warn user if sme locally streaming - // function returns or uses arguments with VL-based types. + // having the '+sme' feature enabled. 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 |= @@ -15196,7 +15188,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, const IdentifierInfo *II = D.getIdentifier(); if (II) { LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(R, S); if (!R.empty()) { NamedDecl *PrevDecl = *R.begin(); @@ -17428,7 +17420,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, RedeclarationKind Redecl = forRedeclarationInCurContext(); if (TUK == TUK_Friend || TUK == TUK_Reference) - Redecl = NotForRedeclaration; + Redecl = RedeclarationKind::NotForRedeclaration; /// Create a new tag decl in C/ObjC. Since the ODR-like semantics for ObjC/C /// implemented asks for structural equivalence checking, the returned decl @@ -18589,7 +18581,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; LookupResult Previous(*this, II, Loc, LookupMemberName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: @@ -18993,8 +18985,9 @@ Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, NewID->setInvalidDecl(); if (II) { - NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, - ForVisibleRedeclaration); + NamedDecl *PrevDecl = + LookupSingleName(S, II, Loc, LookupMemberName, + RedeclarationKind::ForVisibleRedeclaration); if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -19536,6 +19529,13 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Okay, we successfully defined 'Record'. if (Record) { bool Completed = false; + if (S) { + Scope *Parent = S->getParent(); + if (Parent && Parent->isTypeAliasScope() && + Parent->isTemplateParamScope()) + Record->setInvalidDecl(); + } + if (CXXRecord) { if (!CXXRecord->isInvalidDecl()) { // Set access bits correctly on the directly-declared conversions. @@ -19683,7 +19683,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, E = Record->field_end(); (NonBitFields == 0 || ZeroSize) && I != E; ++I) { IsEmpty = false; - if (I->isUnnamedBitfield()) { + if (I->isUnnamedBitField()) { if (!I->isZeroLengthBitField(Context)) ZeroSize = false; } else { @@ -20039,7 +20039,8 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // Verify that there isn't already something declared with this name in this // scope. - LookupResult R(*this, Id, IdLoc, LookupOrdinaryName, ForVisibleRedeclaration); + LookupResult R(*this, Id, IdLoc, LookupOrdinaryName, + RedeclarationKind::ForVisibleRedeclaration); LookupName(R, S); NamedDecl *PrevDecl = R.getAsSingle(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c3bf18a3f79e23ef36e8785a2f63bff335fb381a..363ae93cb62df18752dbbde69e1c954dce20f8ee 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -984,6 +984,21 @@ static void handleErrorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(EA); } +static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + const auto *PD = isa(D) + ? cast(D) + : D->getDeclContext()->getRedeclContext(); + if (const auto *RD = dyn_cast(PD); RD && RD->isLocalClass()) { + S.Diag(AL.getLoc(), + diag::warn_attribute_exclude_from_explicit_instantiation_local_class) + << AL << /*IsMember=*/!isa(D); + return; + } + D->addAttr(::new (S.Context) + ExcludeFromExplicitInstantiationAttr(S.Context, AL)); +} + namespace { /// Determines if a given Expr references any of the given function's /// ParmVarDecls, or the function's implicit `this` parameter (if applicable). @@ -9339,6 +9354,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_Error: handleErrorAttr(S, D, AL); break; + case ParsedAttr::AT_ExcludeFromExplicitInstantiation: + handleExcludeFromExplicitInstantiationAttr(S, D, AL); + break; case ParsedAttr::AT_DiagnoseIf: handleDiagnoseIfAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8c6bae545bfd15e9e6d72c6116d5858eda21cc50..2ef8a15d5238fa1610d1246383f724aab594474f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -896,7 +896,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, assert(VarName && "Cannot have an unnamed binding declaration"); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(Previous, S, /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit()); @@ -951,7 +951,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr, Decomp.getLSquareLoc()); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); // Build the variable that holds the non-decomposed object. bool AddToScope = true; @@ -1453,7 +1453,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, auto DiagnoseBadNumberOfBindings = [&]() -> bool { unsigned NumFields = llvm::count_if( - RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); + RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitField(); }); assert(Bindings.size() != NumFields); S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) << DecompType << (unsigned)Bindings.size() << NumFields << NumFields @@ -1466,7 +1466,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, // E shall not have an anonymous union member, ... unsigned I = 0; for (auto *FD : RD->fields()) { - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) continue; // All the non-static data members are required to be nameable, so they @@ -2067,7 +2067,7 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef, if (Field->isInvalidDecl()) return true; - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) return true; // Anonymous unions with no variant members and empty anonymous structs do not @@ -5509,7 +5509,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, // A declaration for a bit-field that omits the identifier declares an // unnamed bit-field. Unnamed bit-fields are not members and cannot be // initialized. - if (F->isUnnamedBitfield()) + if (F->isUnnamedBitField()) continue; // If we're not generating the implicit copy/move constructor, then we'll @@ -5638,7 +5638,7 @@ static void DiagnoseBaseOrMemInitializerOrder( // 3. Direct fields. for (auto *Field : ClassDecl->fields()) { - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; PopulateKeysForFields(Field, IdealInitKeys); @@ -7030,7 +7030,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { !Record->isLambda()) { bool Complained = false; for (const auto *F : Record->fields()) { - if (F->hasInClassInitializer() || F->isUnnamedBitfield()) + if (F->hasInClassInitializer() || F->isUnnamedBitField()) continue; if (F->getType()->isReferenceType() || @@ -8037,7 +8037,7 @@ protected: for (FieldDecl *Field : Record->fields()) { // C++23 [class.bit]p2: // Unnamed bit-fields are not members ... - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; // Recursively expand anonymous structs. if (Field->isAnonymousStructOrUnion()) { @@ -9396,7 +9396,7 @@ struct SpecialMemberVisitor { return true; for (auto *F : RD->fields()) - if (!F->isInvalidDecl() && !F->isUnnamedBitfield() && + if (!F->isInvalidDecl() && !F->isUnnamedBitField() && getDerived().visitField(F)) return true; @@ -9741,7 +9741,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { AllFieldsAreConst) { bool AnyFields = false; for (auto *F : MD->getParent()->fields()) - if ((AnyFields = !F->isUnnamedBitfield())) + if ((AnyFields = !F->isUnnamedBitField())) break; if (!AnyFields) return false; @@ -10134,7 +10134,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, Sema::TrivialABIHandling TAH, bool Diagnose) { for (const auto *FI : RD->fields()) { - if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) + if (FI->isInvalidDecl() || FI->isUnnamedBitField()) continue; QualType FieldType = S.Context.getBaseElementType(FI->getType()); @@ -11715,7 +11715,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // look through using directives, just look for any ordinary names // as if by qualified name lookup. LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, - ForExternalRedeclaration); + RedeclarationKind::ForExternalRedeclaration); LookupQualifiedName(R, CurContext->getRedeclContext()); NamedDecl *PrevDecl = R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; @@ -12916,7 +12916,7 @@ NamedDecl *Sema::BuildUsingDeclaration( // Do the redeclaration lookup in the current scope. LookupResult Previous(*this, UsingName, LookupUsingDeclName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); Previous.setHideTags(false); if (S) { LookupName(Previous, S); @@ -13159,7 +13159,7 @@ NamedDecl *Sema::BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS, /// In class scope, check if this is a duplicate, for better a diagnostic. DeclarationNameInfo UsingEnumName(ED->getDeclName(), NameLoc); LookupResult Previous(*this, UsingEnumName, LookupUsingDeclName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(Previous, S); @@ -13192,7 +13192,7 @@ NamedDecl *Sema::BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS, UsingShadowDecl *PrevDecl = nullptr; DeclarationNameInfo DNI(EC->getDeclName(), EC->getLocation()); LookupResult Previous(*this, DNI, LookupOrdinaryName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(Previous, S); FilterUsingLookup(S, Previous); @@ -13587,7 +13587,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, LookupResult Previous(*this, NameInfo, LookupOrdinaryName, TemplateParamLists.size() ? forRedeclarationInCurContext() - : ForVisibleRedeclaration); + : RedeclarationKind::ForVisibleRedeclaration); LookupName(Previous, S); // Warn about shadowing the name of a template parameter. @@ -13737,7 +13737,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, // Check if we have a previous declaration with the same name. LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(PrevR, S); // Check we're not shadowing a template parameter. @@ -13983,7 +13983,7 @@ void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) { // implicit special members with this name. DeclarationName Name = FD->getDeclName(); LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName, - ForExternalRedeclaration); + RedeclarationKind::ForExternalRedeclaration); for (auto *D : FD->getParent()->lookup(Name)) if (auto *Acceptable = R.getAcceptableDecl(D)) R.addDecl(Acceptable); @@ -15201,7 +15201,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, for (auto *Field : ClassDecl->fields()) { // FIXME: We should form some kind of AST representation for the implied // memcpy in a union copy operation. - if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) + if (Field->isUnnamedBitField() || Field->getParent()->isUnion()) continue; if (Field->isInvalidDecl()) { @@ -15586,7 +15586,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, for (auto *Field : ClassDecl->fields()) { // FIXME: We should form some kind of AST representation for the implied // memcpy in a union copy operation. - if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) + if (Field->isUnnamedBitField() || Field->getParent()->isUnion()) continue; if (Field->isInvalidDecl()) { @@ -17113,9 +17113,9 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { } const IdentifierInfo *II = D.getIdentifier(); - if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(), - LookupOrdinaryName, - ForVisibleRedeclaration)) { + if (NamedDecl *PrevDecl = + LookupSingleName(S, II, D.getIdentifierLoc(), LookupOrdinaryName, + RedeclarationKind::ForVisibleRedeclaration)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration, except for function parameters in // a function-try-block's catch statement. @@ -17906,7 +17906,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, DeclContext *DC; Scope *DCScope = S; LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForExternalRedeclaration); + RedeclarationKind::ForExternalRedeclaration); bool isTemplateId = D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId; @@ -19242,7 +19242,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; LookupResult Previous(*this, II, Loc, LookupMemberName, - ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d2c77ad61644f05cc85903ecf2a7368780a2283d..2c444d3f8dc484ad8a9c8cbb3af25577efcfcbcb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3902,7 +3902,7 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); } -bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) { +bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc, bool AllowZero) { assert(E && "Invalid expression"); if (E->isValueDependent()) @@ -3920,7 +3920,13 @@ bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) { if (R.isInvalid()) return true; - bool ValueIsPositive = ValueAPS.isStrictlyPositive(); + // GCC allows the value of unroll count to be 0. + // https://gcc.gnu.org/onlinedocs/gcc/Loop-Specific-Pragmas.html says + // "The values of 0 and 1 block any unrolling of the loop." + // The values doesn't have to be strictly positive in '#pragma GCC unroll' and + // '#pragma unroll' cases. + bool ValueIsPositive = + AllowZero ? ValueAPS.isNonNegative() : ValueAPS.isStrictlyPositive(); if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) { Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value) << toString(ValueAPS, 10) << ValueIsPositive; @@ -17522,6 +17528,12 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, if (Converted.isInvalid()) return Converted; E = Converted.get(); + // The 'explicit' case causes us to get a RecoveryExpr. Give up here so we + // don't try to evaluate it later. We also don't want to return the + // RecoveryExpr here, as it results in this call succeeding, thus callers of + // this function will attempt to use 'Value'. + if (isa(E)) + return ExprError(); if (!E->getType()->isIntegralOrUnscopedEnumerationType()) return ExprError(); } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f4a91ececfbb576145f35cd2f27d8732f6ab360f..7582cbd75fec052abc66f28b322a869f37aa5b23 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -9153,7 +9153,7 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, // Do the redeclaration lookup in the current scope. LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, - Sema::NotForRedeclaration); + RedeclarationKind::NotForRedeclaration); LookupParsedName(R, S, &SS); R.suppressDiagnostics(); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 7ea6d733fe5a2d15556fee53eb6133a674267ab5..c79128bc8f39e7e97b5273511d6b05f67224aaa2 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -728,7 +728,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, Sema &SemaRef; DeclarationNameInfo NameInfo; Sema::LookupNameKind LookupKind; - Sema::RedeclarationKind Redecl; + RedeclarationKind Redecl; }; QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), R.redeclarationKind()}; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e86f7578ff0c0569aa2699ab393e84162f1fdca6..793e16df17891459d79a4cfd208d55f24558eb76 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -849,7 +849,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, } for (auto *Field : RDecl->fields()) { - if (Field->isUnnamedBitfield()) + if (Field->isUnnamedBitField()) continue; if (hadError) @@ -1027,7 +1027,7 @@ int InitListChecker::numStructUnionElements(QualType DeclType) { if (auto *CXXRD = dyn_cast(structDecl)) InitializableMembers += CXXRD->getNumBases(); for (const auto *Field : structDecl->fields()) - if (!Field->isUnnamedBitfield()) + if (!Field->isUnnamedBitField()) ++InitializableMembers; if (structDecl->isUnion()) @@ -2175,7 +2175,7 @@ void InitListChecker::CheckStructUnionTypes( // bitfield. for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { - if (!Field->isUnnamedBitfield()) { + if (!Field->isUnnamedBitField()) { CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getEndLoc()); @@ -2338,7 +2338,7 @@ void InitListChecker::CheckStructUnionTypes( if (Field->getType()->isIncompleteArrayType()) break; - if (Field->isUnnamedBitfield()) { + if (Field->isUnnamedBitField()) { // Don't initialize unnamed bitfields, e.g. "int : 20;" ++Field; continue; @@ -2398,7 +2398,7 @@ void InitListChecker::CheckStructUnionTypes( if (HasDesignatedInit && InitializedFields.count(*it)) continue; - if (!it->isUnnamedBitfield() && !it->hasInClassInitializer() && + if (!it->isUnnamedBitField() && !it->hasInClassInitializer() && !it->getType()->isIncompleteArrayType()) { auto Diag = HasDesignatedInit ? diag::warn_missing_designated_field_initializers @@ -2414,7 +2414,7 @@ void InitListChecker::CheckStructUnionTypes( if (!StructuredList && Field != FieldEnd && !RD->isUnion() && !Field->getType()->isIncompleteArrayType()) { for (; Field != FieldEnd && !hadError; ++Field) { - if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer()) + if (!Field->isUnnamedBitField() && !Field->hasInClassInitializer()) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getEndLoc()); @@ -2784,7 +2784,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, unsigned FieldIndex = NumBases; for (auto *FI : RD->fields()) { - if (FI->isUnnamedBitfield()) + if (FI->isUnnamedBitField()) continue; if (declaresSameEntity(KnownField, FI)) { KnownField = FI; @@ -2858,7 +2858,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Find the field that we just initialized. FieldDecl *PrevField = nullptr; for (auto FI = RD->field_begin(); FI != RD->field_end(); ++FI) { - if (FI->isUnnamedBitfield()) + if (FI->isUnnamedBitField()) continue; if (*NextField != RD->field_end() && declaresSameEntity(*FI, **NextField)) @@ -2976,7 +2976,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // If this the first designator, our caller will continue checking // the rest of this struct/class/union subobject. if (IsFirstDesignator) { - if (Field != RD->field_end() && Field->isUnnamedBitfield()) + if (Field != RD->field_end() && Field->isUnnamedBitField()) ++Field; if (NextField) @@ -5585,7 +5585,7 @@ static void TryOrBuildParenListInitialization( for (FieldDecl *FD : RD->fields()) { // Unnamed bitfields should not be initialized at all, either with an arg // or by default. - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) continue; InitializedEntity SubEntity = @@ -7930,7 +7930,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, for (const auto *I : RD->fields()) { if (Index >= ILE->getNumInits()) break; - if (I->isUnnamedBitfield()) + if (I->isUnnamedBitField()) continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) @@ -9532,7 +9532,7 @@ static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc, return false; for (const auto *FI : RD->fields()) { - if (FI->isUnnamedBitfield()) + if (FI->isUnnamedBitField()) continue; if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) { diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index d65f52b8efe81f21fae83fab72d9a431e05a9009..55af414df39f51f6b2b1176626cbcc38941f1207 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4449,7 +4449,8 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, } // Not a GNU local label. - Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); + Res = LookupSingleName(CurScope, II, Loc, LookupLabel, + RedeclarationKind::NotForRedeclaration); // If we found a label, check to see if it is in the same context as us. // When in a Block, we don't want to reuse a label in an enclosing function. if (Res && Res->getDeclContext() != CurContext) @@ -5889,7 +5890,8 @@ void Sema::clearDelayedTypo(TypoExpr *TE) { void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) { DeclarationNameInfo Name(II, IILoc); - LookupResult R(*this, Name, LookupAnyName, Sema::NotForRedeclaration); + LookupResult R(*this, Name, LookupAnyName, + RedeclarationKind::NotForRedeclaration); R.suppressDiagnostics(); R.setHideTags(false); LookupName(R, S); @@ -5899,3 +5901,13 @@ void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) { void Sema::ActOnPragmaDump(Expr *E) { E->dump(); } + +RedeclarationKind Sema::forRedeclarationInCurContext() const { + // A declaration with an owning module for linkage can never link against + // anything that is not visible. We don't need to check linkage here; if + // the context has internal linkage, redeclaration lookup won't find things + // from other TUs, and we can't safely compute linkage yet in general. + if (cast(CurContext)->getOwningModuleForLinkage(/*IgnoreLinkage*/ true)) + return RedeclarationKind::ForVisibleRedeclaration; + return RedeclarationKind::ForExternalRedeclaration; +} diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 2ddf9d70263a094d1cf0d9e7fa387247771521a5..ad118ac90e4aa6a23db950cc77e9179f85ea9aa0 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaInternal.h" @@ -475,6 +476,9 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, getASTContext().setCurrentNamedModule(Mod); + if (auto *Listener = getASTMutationListener()) + Listener->EnteringModulePurview(); + // We already potentially made an implicit import (in the case of a module // implementation unit importing its interface). Make this module visible // and return the import decl to be added to the current TU. @@ -999,6 +1003,10 @@ Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) { } } + // Anything exported from a module should never be considered unused. + for (auto *Exported : ED->decls()) + Exported->markUsed(getASTContext()); + return D; } diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 59f65eaf47a6daab2d8d622a6f1f584732905668..190739fa02e9327ad43d16ac3ecbd4e366e719c7 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -14,6 +14,7 @@ #include "clang/Sema/SemaOpenACC.h" #include "clang/AST/StmtOpenACC.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/OpenACCKinds.h" #include "clang/Sema/Sema.h" #include "llvm/Support/Casting.h" @@ -90,6 +91,17 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, default: return false; } + case OpenACCClauseKind::NumWorkers: + case OpenACCClauseKind::VectorLength: + switch (DirectiveKind) { + case OpenACCDirectiveKind::Parallel: + case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::KernelsLoop: + return true; + default: + return false; + } default: // Do nothing so we can go to the 'unimplemented' diagnostic instead. return true; @@ -218,6 +230,44 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getConditionExpr(), Clause.getEndLoc()); } + case OpenACCClauseKind::NumWorkers: { + // 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; + + assert(Clause.getIntExprs().size() == 1 && + "Invalid number of expressions for NumWorkers"); + return OpenACCNumWorkersClause::Create( + getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), + Clause.getIntExprs()[0], Clause.getEndLoc()); + } + case OpenACCClauseKind::VectorLength: { + // 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; + + assert(Clause.getIntExprs().size() == 1 && + "Invalid number of expressions for VectorLength"); + return OpenACCVectorLengthClause::Create( + getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), + Clause.getIntExprs()[0], Clause.getEndLoc()); + } default: break; } @@ -248,6 +298,96 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, } } +ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK, + OpenACCClauseKind CK, SourceLocation Loc, + Expr *IntExpr) { + + assert(((DK != OpenACCDirectiveKind::Invalid && + CK == OpenACCClauseKind::Invalid) || + (DK == OpenACCDirectiveKind::Invalid && + CK != OpenACCClauseKind::Invalid)) && + "Only one of directive or clause kind should be provided"); + + class IntExprConverter : public Sema::ICEConvertDiagnoser { + OpenACCDirectiveKind DirectiveKind; + OpenACCClauseKind ClauseKind; + Expr *IntExpr; + + public: + IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + Expr *IntExpr) + : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, + /*Suppress=*/false, + /*SuppressConversion=*/true), + DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {} + + bool match(QualType T) override { + // OpenACC spec just calls this 'integer expression' as having an + // 'integer type', so fall back on C99's 'integer type'. + return T->isIntegerType(); + } + SemaBase::SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) override { + if (ClauseKind != OpenACCClauseKind::Invalid) + return S.Diag(Loc, diag::err_acc_int_expr_requires_integer) << + /*Clause=*/0 << ClauseKind << T; + + return S.Diag(Loc, diag::err_acc_int_expr_requires_integer) << + /*Directive=*/1 << DirectiveKind << T; + } + + SemaBase::SemaDiagnosticBuilder + diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override { + return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type) + << T << IntExpr->getSourceRange(); + } + + SemaBase::SemaDiagnosticBuilder + diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T, + QualType ConvTy) override { + return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion) + << T << ConvTy; + } + + SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S, + CXXConversionDecl *Conv, + QualType ConvTy) override { + return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + SemaBase::SemaDiagnosticBuilder + diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override { + return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T; + } + + SemaBase::SemaDiagnosticBuilder + noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override { + return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + SemaBase::SemaDiagnosticBuilder + diagnoseConversion(Sema &S, SourceLocation Loc, QualType T, + QualType ConvTy) override { + llvm_unreachable("conversion functions are permitted"); + } + } IntExprDiagnoser(DK, CK, IntExpr); + + ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion( + Loc, IntExpr, IntExprDiagnoser); + if (IntExprResult.isInvalid()) + return ExprError(); + + IntExpr = IntExprResult.get(); + if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType()) + return ExprError(); + + // TODO OpenACC: Do we want to perform usual unary conversions here? When + // doing codegen we might find that is necessary, but skip it for now. + return IntExpr; +} + bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc) { return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index d229ef650bccb0e277ebf7d9319e5686519d6c0a..3e9f6cba25076d1ccd7b35c000a539e5460642ed 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -24944,7 +24944,7 @@ ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S, // Check for conflicting previous declaration. DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc); LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, - Sema::ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); Previous.suppressDiagnostics(); SemaRef.LookupName(Previous, S); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index adc319e97b76250c24a5b207489e3f2272fecabc..48d6264029e9bfe900c7c62f2eac399cc1d0661c 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6563,11 +6563,14 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, HadMultipleCandidates); if (Result.isInvalid()) return true; - // Record usage of conversion in an implicit cast. - From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), - CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind(), - SemaRef.CurFPFeatureOverrides()); + + // Replace the conversion with a RecoveryExpr, so we don't try to + // instantiate it later, but can further diagnose here. + Result = SemaRef.CreateRecoveryExpr(From->getBeginLoc(), From->getEndLoc(), + From, Result.get()->getType()); + if (Result.isInvalid()) + return true; + From = Result.get(); } return false; } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index a0339273a0ba35ec6826ae58ab2e9f1e683cf2a0..7cd494b42250d4d66bc77357b6a24e32021cb1e6 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -109,9 +109,18 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable); } else if (PragmaName == "unroll") { // #pragma unroll N - if (ValueExpr) - SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric); - else + if (ValueExpr) { + llvm::APSInt ValueAPS; + ExprResult R = S.VerifyIntegerConstantExpression(ValueExpr, &ValueAPS); + assert(!R.isInvalid() && "unroll count value must be a valid value, it's " + "should be checked in Sema::CheckLoopHintExpr"); + (void)R; + // The values of 0 and 1 block any unrolling of the loop. + if (ValueAPS.isZero() || ValueAPS.isOne()) + SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Disable); + else + SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric); + } else SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable); } else if (PragmaName == "nounroll_and_jam") { SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable); @@ -142,7 +151,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, if (Option == LoopHintAttr::VectorizeWidth) { assert((ValueExpr || (StateLoc && StateLoc->Ident)) && "Attribute must have a valid value expression or argument."); - if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) + if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(), + /*AllowZero=*/false)) return nullptr; if (StateLoc && StateLoc->Ident && StateLoc->Ident->isStr("scalable")) State = LoopHintAttr::ScalableWidth; @@ -152,7 +162,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, Option == LoopHintAttr::UnrollCount || Option == LoopHintAttr::PipelineInitiationInterval) { assert(ValueExpr && "Attribute must have a valid value expression."); - if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) + if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(), + /*AllowZero=*/false)) return nullptr; State = LoopHintAttr::Numeric; } else if (Option == LoopHintAttr::Vectorize || diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 95171359f0ab174ddf9be131baa65a3acc6cef84..d4976f9d0d11d81e8b06f7321034bef56403243b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -972,8 +972,9 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S, SourceLocation Loc, const IdentifierInfo *Name) { - NamedDecl *PrevDecl = SemaRef.LookupSingleName( - S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); + NamedDecl *PrevDecl = + SemaRef.LookupSingleName(S, Name, Loc, Sema::LookupOrdinaryName, + RedeclarationKind::ForVisibleRedeclaration); if (PrevDecl && PrevDecl->isTemplateParameter()) SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl); } @@ -3043,6 +3044,11 @@ FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias( return nullptr; LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), RHSDeductionGuide, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) + return nullptr; // Build a new template parameter list for the synthesized aggregate deduction // guide by transforming the one from RHSDeductionGuide. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 7cd428de0bb32d2a29d36e1bf60b638b0bd6b315..3e6676f21c9be09a8c29c1c2c41a0be54289d3f3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2150,7 +2150,8 @@ TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) { return LH; // Generate error if there is a problem with the value. - if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation())) + if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation(), + LH->getOption() == LoopHintAttr::UnrollCount)) return LH; // Create new LoopHintValueAttr with integral expression in place of the diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6d359c5a9a024cb0e5e281b010e698e0a74f6287..caa07abb61fe349b91ec5aeb101dde2da5725328 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2296,7 +2296,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( SemaRef, Function->getDeclName(), SourceLocation(), D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage : Sema::LookupOrdinaryName, - D->isLocalExternDecl() ? Sema::ForExternalRedeclaration + D->isLocalExternDecl() ? RedeclarationKind::ForExternalRedeclaration : SemaRef.forRedeclarationInCurContext()); if (DependentFunctionTemplateSpecializationInfo *DFTSI = @@ -2697,7 +2697,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( Method->setInvalidDecl(); LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, - Sema::ForExternalRedeclaration); + RedeclarationKind::ForExternalRedeclaration); bool IsExplicitSpecialization = false; @@ -3365,7 +3365,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { // fact, it's not really even possible in non-class scopes). bool CheckRedeclaration = Owner->isRecord(); LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName, - Sema::ForVisibleRedeclaration); + RedeclarationKind::ForVisibleRedeclaration); UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(), @@ -5388,7 +5388,7 @@ void Sema::BuildVariableInstantiation( *this, NewVar->getDeclName(), NewVar->getLocation(), NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage : Sema::LookupOrdinaryName, - NewVar->isLocalExternDecl() ? Sema::ForExternalRedeclaration + NewVar->isLocalExternDecl() ? RedeclarationKind::ForExternalRedeclaration : forRedeclarationInCurContext()); if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() && diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 1b31df8d97fba2931ad741931725223ddb94c067..fddc3545ecb61c5b9a351e8b2554ebdf9de31251 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -4729,7 +4729,8 @@ static bool shouldHaveNullability(QualType T) { // It's unclear whether the pragma's behavior is useful for C++. // e.g. treating type-aliases and template-type-parameters differently // from types of declarations can be surprising. - !isa(T->getCanonicalTypeInternal()); + !isa( + T->getCanonicalTypeInternal()); } static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index eb05783a6219dc6b55b161f95ad89a023f9295a2..ade33ec65038fdb3abc6b10708aec3f7a898163b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11158,6 +11158,52 @@ void OpenACCClauseTransform::VisitSelfClause( ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(), ParsedClause.getEndLoc()); } + +template +void OpenACCClauseTransform::VisitNumWorkersClause( + const OpenACCNumWorkersClause &C) { + Expr *IntExpr = const_cast(C.getIntExpr()); + assert(IntExpr && "num_workers clause constructed with invalid int expr"); + + ExprResult Res = Self.TransformExpr(IntExpr); + if (!Res.isUsable()) + return; + + Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid, + C.getClauseKind(), + C.getBeginLoc(), Res.get()); + if (!Res.isUsable()) + return; + + ParsedClause.setIntExprDetails(Res.get()); + NewClause = OpenACCNumWorkersClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getIntExprs()[0], + ParsedClause.getEndLoc()); +} + +template +void OpenACCClauseTransform::VisitVectorLengthClause( + const OpenACCVectorLengthClause &C) { + Expr *IntExpr = const_cast(C.getIntExpr()); + assert(IntExpr && "vector_length clause constructed with invalid int expr"); + + ExprResult Res = Self.TransformExpr(IntExpr); + if (!Res.isUsable()) + return; + + Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid, + C.getClauseKind(), + C.getBeginLoc(), Res.get()); + if (!Res.isUsable()) + return; + + ParsedClause.setIntExprDetails(Res.get()); + NewClause = OpenACCVectorLengthClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getIntExprs()[0], + ParsedClause.getEndLoc()); +} } // namespace template OpenACCClause *TreeTransform::TransformOpenACCClause( diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b28df03b4a95e95a2a91e4103a9c458fd40197c4..44e23919ea18e0aea165d30555fd4728869ec612 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11786,6 +11786,18 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc, CondExpr, EndLoc); } + case OpenACCClauseKind::NumWorkers: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *IntExpr = readSubExpr(); + return OpenACCNumWorkersClause::Create(getContext(), BeginLoc, LParenLoc, + IntExpr, EndLoc); + } + case OpenACCClauseKind::VectorLength: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *IntExpr = readSubExpr(); + return OpenACCVectorLengthClause::Create(getContext(), BeginLoc, LParenLoc, + IntExpr, EndLoc); + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -11814,9 +11826,7 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::VectorLength: case OpenACCClauseKind::NumGangs: - case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::DeviceType: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index b2a078b6d80f467d03560e155d83d6ccd19bf17d..6dd87b5d200db6141dfb58ec7e56b8ff95c0bda1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4734,11 +4734,19 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, } template -static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, - ASTWriter::RecordData &Record) { +static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec) { for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); I != E; ++I) { - Writer.AddDeclRef(*I, Record); + Writer.GetDeclRef(*I); + } +} + +template +static void AddLazyVectorEmiitedDecls(ASTWriter &Writer, Vector &Vec, + ASTWriter::RecordData &Record) { + for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); + I != E; ++I) { + Writer.AddEmittedDeclRef(*I, Record); } } @@ -4835,24 +4843,10 @@ void ASTWriter::computeNonAffectingInputFiles() { FileMgr.trackVFSUsage(false); } -ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, - Module *WritingModule) { - using namespace llvm; - - bool isModule = WritingModule != nullptr; - - // Make sure that the AST reader knows to finalize itself. - if (Chain) - Chain->finalizeForWriting(); - +void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) { ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - // This needs to be done very early, since everything that writes - // SourceLocations or FileIDs depends on it. - computeNonAffectingInputFiles(); - - writeUnhashedControlBlock(PP, Context); + bool isModule = WritingModule != nullptr; // Set up predefined declaration IDs. auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { @@ -4888,103 +4882,269 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, RegisterPredefDecl(Context.TypePackElementDecl, PREDEF_DECL_TYPE_PACK_ELEMENT_ID); - // Build a record containing all of the tentative definitions in this file, in + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + + // Force all top level declarations to be emitted. + // + // We start emitting top level declarations from the module purview to + // implement the eliding unreachable declaration feature. + for (const auto *D : TU->noload_decls()) { + if (D->isFromASTFile()) + continue; + + if (GeneratingReducedBMI) { + if (D->isFromExplicitGlobalModule()) + continue; + + // Don't force emitting static entities. + // + // Technically, all static entities shouldn't be in reduced BMI. The + // language also specifies that the program exposes TU-local entities + // is ill-formed. However, in practice, there are a lot of projects + // uses `static inline` in the headers. So we can't get rid of all + // static entities in reduced BMI now. + if (auto *ND = dyn_cast(D); + ND && ND->getFormalLinkage() == Linkage::Internal) + continue; + } + + GetDeclRef(D); + } + + if (GeneratingReducedBMI) + return; + + // Writing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. RecordData TentativeDefinitions; - AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); + AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions); - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; + // Writing all of the file scoped decls in this file. if (!isModule) - AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, - UnusedFileScopedDecls); + AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls); - // Build a record containing all of the delegating constructors we still need + // Writing all of the delegating constructors we still need // to resolve. - RecordData DelegatingCtorDecls; if (!isModule) - AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls); - // Write the set of weak, undeclared identifiers. We always write the - // entire table, since later PCH files in a PCH chain are only interested in - // the results at the end of the chain. - RecordData WeakUndeclaredIdentifiers; - for (const auto &WeakUndeclaredIdentifierList : - SemaRef.WeakUndeclaredIdentifiers) { - const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first; - for (const auto &WI : WeakUndeclaredIdentifierList.second) { - AddIdentifierRef(II, WeakUndeclaredIdentifiers); - AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + // Writing all of the ext_vector declarations. + AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls); + + // Writing all of the VTable uses information. + if (!SemaRef.VTableUses.empty()) + for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) + GetDeclRef(SemaRef.VTableUses[I].first); + + // Writing all of the UnusedLocalTypedefNameCandidates. + for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) + GetDeclRef(TD); + + // Writing all of pending implicit instantiations. + for (const auto &I : SemaRef.PendingInstantiations) + GetDeclRef(I.first); + assert(SemaRef.PendingLocalImplicitInstantiations.empty() && + "There are local ones at end of translation unit!"); + + // Writing some declaration references. + if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { + GetDeclRef(SemaRef.getStdNamespace()); + GetDeclRef(SemaRef.getStdBadAlloc()); + GetDeclRef(SemaRef.getStdAlignValT()); + } + + if (Context.getcudaConfigureCallDecl()) + GetDeclRef(Context.getcudaConfigureCallDecl()); + + // Writing all of the known namespaces. + for (const auto &I : SemaRef.KnownNamespaces) + if (!I.second) + GetDeclRef(I.first); + + // Writing all used, undefined objects that require definitions. + SmallVector, 16> Undefined; + SemaRef.getUndefinedButUsed(Undefined); + for (const auto &I : Undefined) + GetDeclRef(I.first); + + // Writing all delete-expressions that we would like to + // analyze later in AST. + if (!isModule) + for (const auto &DeleteExprsInfo : + SemaRef.getMismatchingDeleteExpressions()) + GetDeclRef(DeleteExprsInfo.first); + + // Make sure visible decls, added to DeclContexts previously loaded from + // an AST file, are registered for serialization. Likewise for template + // specializations added to imported templates. + for (const auto *I : DeclsToEmitEvenIfUnreferenced) + GetDeclRef(I); + DeclsToEmitEvenIfUnreferenced.clear(); + + // Make sure all decls associated with an identifier are registered for + // serialization, if we're storing decls with identifiers. + if (!WritingModule || !getLangOpts().CPlusPlus) { + llvm::SmallVector IIs; + for (const auto &ID : SemaRef.PP.getIdentifierTable()) { + const IdentifierInfo *II = ID.second; + if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) + IIs.push_back(II); } + // Sort the identifiers to visit based on their name. + llvm::sort(IIs, llvm::deref>()); + for (const IdentifierInfo *II : IIs) + for (const Decl *D : SemaRef.IdResolver.decls(II)) + GetDeclRef(D); } - // Build a record containing all of the ext_vector declarations. + // Write all of the DeclsToCheckForDeferredDiags. + for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) + GetDeclRef(D); +} + +void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) { + ASTContext &Context = SemaRef.Context; + + bool isModule = WritingModule != nullptr; + + // Write the record containing external, unnamed definitions. + if (!EagerlyDeserializedDecls.empty()) + Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); + + if (!ModularCodegenDecls.empty()) + Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); + + // Write the record containing tentative definitions. + RecordData TentativeDefinitions; + AddLazyVectorEmiitedDecls(*this, SemaRef.TentativeDefinitions, + TentativeDefinitions); + if (!TentativeDefinitions.empty()) + Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); + + // Write the record containing unused file scoped decls. + RecordData UnusedFileScopedDecls; + if (!isModule) + AddLazyVectorEmiitedDecls(*this, SemaRef.UnusedFileScopedDecls, + UnusedFileScopedDecls); + if (!UnusedFileScopedDecls.empty()) + Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + + // Write the record containing ext_vector type names. RecordData ExtVectorDecls; - AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); + AddLazyVectorEmiitedDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); + if (!ExtVectorDecls.empty()) + Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - // Build a record containing all of the VTable uses information. + // Write the record containing VTable uses information. RecordData VTableUses; if (!SemaRef.VTableUses.empty()) { for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); + CXXRecordDecl *D = SemaRef.VTableUses[I].first; + if (!wasDeclEmitted(D)) + continue; + + AddDeclRef(D, VTableUses); AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); + VTableUses.push_back(SemaRef.VTablesUsed[D]); } + Stream.EmitRecord(VTABLE_USES, VTableUses); } - // Build a record containing all of the UnusedLocalTypedefNameCandidates. + // Write the record containing potentially unused local typedefs. RecordData UnusedLocalTypedefNameCandidates; for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) - AddDeclRef(TD, UnusedLocalTypedefNameCandidates); + AddEmittedDeclRef(TD, UnusedLocalTypedefNameCandidates); + if (!UnusedLocalTypedefNameCandidates.empty()) + Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, + UnusedLocalTypedefNameCandidates); - // Build a record containing all of pending implicit instantiations. + // Write the record containing pending implicit instantiations. RecordData PendingInstantiations; for (const auto &I : SemaRef.PendingInstantiations) { + if (!wasDeclEmitted(I.first)) + continue; + AddDeclRef(I.first, PendingInstantiations); AddSourceLocation(I.second, PendingInstantiations); } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); + if (!PendingInstantiations.empty()) + Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - // Build a record containing some declaration references. + // Write the record containing declaration references of Sema. RecordData SemaDeclRefs; if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { - AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdAlignValT(), SemaDeclRefs); + auto AddEmittedDeclRefOrZero = [this, &SemaDeclRefs](Decl *D) { + if (!D || !wasDeclEmitted(D)) + SemaDeclRefs.push_back(0); + else + SemaDeclRefs.push_back(getDeclID(D)); + }; + + AddEmittedDeclRefOrZero(SemaRef.getStdNamespace()); + AddEmittedDeclRefOrZero(SemaRef.getStdBadAlloc()); + AddEmittedDeclRefOrZero(SemaRef.getStdAlignValT()); } + if (!SemaDeclRefs.empty()) + Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); + // Write the record containing decls to be checked for deferred diags. + SmallVector DeclsToCheckForDeferredDiags; + for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) + if (wasDeclEmitted(D)) + DeclsToCheckForDeferredDiags.push_back(getDeclID(D)); + if (!DeclsToCheckForDeferredDiags.empty()) + Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, + DeclsToCheckForDeferredDiags); + + // Write the record containing CUDA-specific declaration references. RecordData CUDASpecialDeclRefs; - if (Context.getcudaConfigureCallDecl()) { - AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs); + if (auto *CudaCallDecl = Context.getcudaConfigureCallDecl(); + CudaCallDecl && wasDeclEmitted(CudaCallDecl)) { + AddDeclRef(CudaCallDecl, CUDASpecialDeclRefs); + Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); } - // Build a record containing all of the known namespaces. + // Write the delegating constructors. + RecordData DelegatingCtorDecls; + if (!isModule) + AddLazyVectorEmiitedDecls(*this, SemaRef.DelegatingCtorDecls, + DelegatingCtorDecls); + if (!DelegatingCtorDecls.empty()) + Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); + + // Write the known namespaces. RecordData KnownNamespaces; for (const auto &I : SemaRef.KnownNamespaces) { - if (!I.second) + if (!I.second && wasDeclEmitted(I.first)) AddDeclRef(I.first, KnownNamespaces); } + if (!KnownNamespaces.empty()) + Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - // Build a record of all used, undefined objects that require definitions. + // Write the undefined internal functions and variables, and inline functions. RecordData UndefinedButUsed; - SmallVector, 16> Undefined; SemaRef.getUndefinedButUsed(Undefined); for (const auto &I : Undefined) { + if (!wasDeclEmitted(I.first)) + continue; + AddDeclRef(I.first, UndefinedButUsed); AddSourceLocation(I.second, UndefinedButUsed); } + if (!UndefinedButUsed.empty()) + Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - // Build a record containing all delete-expressions that we would like to + // Write all delete-expressions that we would like to // analyze later in AST. RecordData DeleteExprsToAnalyze; - if (!isModule) { for (const auto &DeleteExprsInfo : SemaRef.getMismatchingDeleteExpressions()) { + if (!wasDeclEmitted(DeleteExprsInfo.first)) + continue; + AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); for (const auto &DeleteLoc : DeleteExprsInfo.second) { @@ -4993,6 +5153,44 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } } } + if (!DeleteExprsToAnalyze.empty()) + Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); +} + +ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, + Module *WritingModule) { + using namespace llvm; + + bool isModule = WritingModule != nullptr; + + // Make sure that the AST reader knows to finalize itself. + if (Chain) + Chain->finalizeForWriting(); + + ASTContext &Context = SemaRef.Context; + Preprocessor &PP = SemaRef.PP; + + // This needs to be done very early, since everything that writes + // SourceLocations or FileIDs depends on it. + computeNonAffectingInputFiles(); + + writeUnhashedControlBlock(PP, Context); + + // Write the set of weak, undeclared identifiers. We always write the + // entire table, since later PCH files in a PCH chain are only interested in + // the results at the end of the chain. + RecordData WeakUndeclaredIdentifiers; + for (const auto &WeakUndeclaredIdentifierList : + SemaRef.WeakUndeclaredIdentifiers) { + const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first; + for (const auto &WI : WeakUndeclaredIdentifierList.second) { + AddIdentifierRef(II, WeakUndeclaredIdentifiers); + AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); + AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + } + } + + PrepareWritingSpecialDecls(SemaRef); // Write the control block WriteControlBlock(PP, Context, isysroot); @@ -5010,66 +5208,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } - const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - - // Force all top level declarations to be emitted. - // - // We start emitting top level declarations from the module purview to - // implement the eliding unreachable declaration feature. - for (const auto *D : TU->noload_decls()) { - if (D->isFromASTFile()) - continue; - - if (GeneratingReducedBMI && D->isFromExplicitGlobalModule()) - continue; - - GetDeclRef(D); - } - - // If the translation unit has an anonymous namespace, and we don't already - // have an update block for it, write it as an update block. - // FIXME: Why do we not do this if there's already an update block? - if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { - ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; - if (Record.empty()) - Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); - } - - // Add update records for all mangling numbers and static local numbers. - // These aren't really update records, but this is a convenient way of - // tagging this rare extra data onto the declarations. - for (const auto &Number : Context.MangleNumbers) - if (!Number.first->isFromASTFile()) - DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER, - Number.second)); - for (const auto &Number : Context.StaticLocalNumbers) - if (!Number.first->isFromASTFile()) - DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, - Number.second)); - - // Make sure visible decls, added to DeclContexts previously loaded from - // an AST file, are registered for serialization. Likewise for template - // specializations added to imported templates. - for (const auto *I : DeclsToEmitEvenIfUnreferenced) { - GetDeclRef(I); - } - - // Make sure all decls associated with an identifier are registered for - // serialization, if we're storing decls with identifiers. - if (!WritingModule || !getLangOpts().CPlusPlus) { - llvm::SmallVector IIs; - for (const auto &ID : PP.getIdentifierTable()) { - const IdentifierInfo *II = ID.second; - if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) - IIs.push_back(II); - } - // Sort the identifiers to visit based on their name. - llvm::sort(IIs, llvm::deref>()); - for (const IdentifierInfo *II : IIs) - for (const Decl *D : SemaRef.IdResolver.decls(II)) - GetDeclRef(D); - } - // For method pool in the module, if it contains an entry for a selector, // the entry should be complete, containing everything introduced by that // module and all modules it imports. It's possible that the entry is out of @@ -5160,11 +5298,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Buffer.data(), Buffer.size()); } - // Build a record containing all of the DeclsToCheckForDeferredDiags. - SmallVector DeclsToCheckForDeferredDiags; - for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) - DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); - WriteDeclAndTypes(Context); WriteFileDeclIDsMap(); @@ -5186,71 +5319,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); - // Write the record containing external, unnamed definitions. - if (!EagerlyDeserializedDecls.empty()) - Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); - - if (!ModularCodegenDecls.empty()) - Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + WriteSpecialDeclRecords(SemaRef); // Write the record containing weak undeclared identifiers. if (!WeakUndeclaredIdentifiers.empty()) Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, WeakUndeclaredIdentifiers); - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(VTABLE_USES, VTableUses); - - // Write the record containing potentially unused local typedefs. - if (!UnusedLocalTypedefNameCandidates.empty()) - Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, - UnusedLocalTypedefNameCandidates); - - // Write the record containing pending implicit instantiations. - if (!PendingInstantiations.empty()) - Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); - - // Write the record containing decls to be checked for deferred diags. - if (!DeclsToCheckForDeferredDiags.empty()) - Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, - DeclsToCheckForDeferredDiags); - - // Write the record containing CUDA-specific declaration references. - if (!CUDASpecialDeclRefs.empty()) - Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); - - // Write the delegating constructors. - if (!DelegatingCtorDecls.empty()) - Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); - - // Write the known namespaces. - if (!KnownNamespaces.empty()) - Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - - // Write the undefined internal functions and variables, and inline functions. - if (!UndefinedButUsed.empty()) - Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - - if (!DeleteExprsToAnalyze.empty()) - Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); - if (!WritingModule) { // Write the submodules that were imported, if any. struct ModuleInfo { @@ -5315,6 +5390,41 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, return backpatchSignature(); } +void ASTWriter::EnteringModulePurview() { + // In C++20 named modules, all entities before entering the module purview + // lives in the GMF. + if (GeneratingReducedBMI) + DeclUpdatesFromGMF.swap(DeclUpdates); +} + +// Add update records for all mangling numbers and static local numbers. +// These aren't really update records, but this is a convenient way of +// tagging this rare extra data onto the declarations. +void ASTWriter::AddedManglingNumber(const Decl *D, unsigned Number) { + if (D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_MANGLING_NUMBER, Number)); +} +void ASTWriter::AddedStaticLocalNumbers(const Decl *D, unsigned Number) { + if (D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, Number)); +} + +void ASTWriter::AddedAnonymousNamespace(const TranslationUnitDecl *TU, + NamespaceDecl *AnonNamespace) { + // If the translation unit has an anonymous namespace, and we don't already + // have an update block for it, write it as an update block. + // FIXME: Why do we not do this if there's already an update block? + if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { + ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; + if (Record.empty()) + Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); + } +} + void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { // Keep writing types, declarations, and declaration update records // until we've emitted all of them. @@ -5849,6 +5959,13 @@ TypeID ASTWriter::getTypeID(QualType T) const { }); } +void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) { + if (!wasDeclEmitted(D)) + return; + + Record.push_back(GetDeclRef(D)); +} + void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { Record.push_back(GetDeclRef(D)); } @@ -5860,6 +5977,14 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { return 0; } + // If the DeclUpdate from the GMF gets touched, emit it. + if (auto *Iter = DeclUpdatesFromGMF.find(D); + Iter != DeclUpdatesFromGMF.end()) { + for (DeclUpdate &Update : Iter->second) + DeclUpdates[D].push_back(Update); + DeclUpdatesFromGMF.erase(Iter); + } + // If D comes from an AST file, its declaration ID is already known and // fixed. if (D->isFromASTFile()) @@ -7532,6 +7657,18 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { AddStmt(const_cast(SC->getConditionExpr())); return; } + case OpenACCClauseKind::NumWorkers: { + const auto *NWC = cast(C); + writeSourceLocation(NWC->getLParenLoc()); + AddStmt(const_cast(NWC->getIntExpr())); + return; + } + case OpenACCClauseKind::VectorLength: { + const auto *NWC = cast(C); + writeSourceLocation(NWC->getLParenLoc()); + AddStmt(const_cast(NWC->getIntExpr())); + return; + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -7560,9 +7697,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::VectorLength: case OpenACCClauseKind::NumGangs: - case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::DeviceType: diff --git a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp index f02d20d45678b3bd4cc4edd2ffecb8aa6dc7416c..c7479d74eafc3349b507b06f5629c83a53a806dc 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -56,23 +56,23 @@ public: private: // These are known in the LLVM project. The pairs are in the following form: - // {{{namespace, call}, argument-count}, {callback, kind}} + // {{match-mode, {namespace, call}, argument-count}, {callback, kind}} const CallDescriptionMap> CDM = { - {{{"llvm", "cast"}, 1}, + {{CDM::SimpleFunc, {"llvm", "cast"}, 1}, {&CastValueChecker::evalCast, CallKind::Function}}, - {{{"llvm", "dyn_cast"}, 1}, + {{CDM::SimpleFunc, {"llvm", "dyn_cast"}, 1}, {&CastValueChecker::evalDynCast, CallKind::Function}}, - {{{"llvm", "cast_or_null"}, 1}, + {{CDM::SimpleFunc, {"llvm", "cast_or_null"}, 1}, {&CastValueChecker::evalCastOrNull, CallKind::Function}}, - {{{"llvm", "dyn_cast_or_null"}, 1}, + {{CDM::SimpleFunc, {"llvm", "dyn_cast_or_null"}, 1}, {&CastValueChecker::evalDynCastOrNull, CallKind::Function}}, - {{{"clang", "castAs"}, 0}, + {{CDM::CXXMethod, {"clang", "castAs"}, 0}, {&CastValueChecker::evalCastAs, CallKind::Method}}, - {{{"clang", "getAs"}, 0}, + {{CDM::CXXMethod, {"clang", "getAs"}, 0}, {&CastValueChecker::evalGetAs, CallKind::Method}}, - {{{"llvm", "isa"}, 1}, + {{CDM::SimpleFunc, {"llvm", "isa"}, 1}, {&CastValueChecker::evalIsa, CallKind::InstanceOf}}, - {{{"llvm", "isa_and_nonnull"}, 1}, + {{CDM::SimpleFunc, {"llvm", "isa_and_nonnull"}, 1}, {&CastValueChecker::evalIsaAndNonNull, CallKind::InstanceOf}}}; void evalCast(const CallEvent &Call, DefinedOrUnknownSVal DV, diff --git a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index be7be15022d360d665b63777cbb7a588cdd3f9e5..3a0a01c23de03eebef3e3ef32527650cf5d84032 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -43,7 +43,8 @@ class ChrootChecker : public Checker { // This bug refers to possibly break out of a chroot() jail. const BugType BT_BreakJail{this, "Break out of jail"}; - const CallDescription Chroot{{"chroot"}, 1}, Chdir{{"chdir"}, 1}; + const CallDescription Chroot{CDM::CLibrary, {"chroot"}, 1}, + Chdir{CDM::CLibrary, {"chdir"}, 1}; public: ChrootChecker() {} diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp index c46ebee0c94ff48eefc47295fc2a3976d2c3ae6b..6076a6bc789737a8f9bf823ec80726740f8f9c5c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp @@ -70,13 +70,15 @@ private: using EvalFn = std::function; const CallDescriptionMap TestCalls{ - {{{"ErrnoTesterChecker_setErrno"}, 1}, &ErrnoTesterChecker::evalSetErrno}, - {{{"ErrnoTesterChecker_getErrno"}, 0}, &ErrnoTesterChecker::evalGetErrno}, - {{{"ErrnoTesterChecker_setErrnoIfError"}, 0}, + {{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrno"}, 1}, + &ErrnoTesterChecker::evalSetErrno}, + {{CDM::SimpleFunc, {"ErrnoTesterChecker_getErrno"}, 0}, + &ErrnoTesterChecker::evalGetErrno}, + {{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrnoIfError"}, 0}, &ErrnoTesterChecker::evalSetErrnoIfError}, - {{{"ErrnoTesterChecker_setErrnoIfErrorRange"}, 0}, + {{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrnoIfErrorRange"}, 0}, &ErrnoTesterChecker::evalSetErrnoIfErrorRange}, - {{{"ErrnoTesterChecker_setErrnoCheckState"}, 0}, + {{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrnoCheckState"}, 0}, &ErrnoTesterChecker::evalSetErrnoCheckState}}; }; diff --git a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp index 2e31c16e457c2e4566cd75f326c3d7bd66740654..cd1dd1b2fc511fd27af989998eb837de9aa7f070 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp @@ -27,8 +27,8 @@ using namespace ento; namespace { class MmapWriteExecChecker : public Checker { - CallDescription MmapFn; - CallDescription MprotectFn; + CallDescription MmapFn{CDM::CLibrary, {"mmap"}, 6}; + CallDescription MprotectFn{CDM::CLibrary, {"mprotect"}, 3}; static int ProtWrite; static int ProtExec; static int ProtRead; @@ -36,7 +36,6 @@ class MmapWriteExecChecker : public Checker { "Security"}; public: - MmapWriteExecChecker() : MmapFn({"mmap"}, 6), MprotectFn({"mprotect"}, 3) {} void checkPreCall(const CallEvent &Call, CheckerContext &C) const; int ProtExecOv; int ProtReadOv; diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp index 2f2df63468b4b15cb67417b81b8d8074fa5d8d89..23014ff954870dede321451dc75215fa9282139b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp @@ -118,8 +118,7 @@ static void checkObjCUnusedIvar(const ObjCImplementationDecl *D, // (d) are unnamed bitfields if (Ivar->getAccessControl() != ObjCIvarDecl::Private || Ivar->hasAttr() || Ivar->hasAttr() || - Ivar->hasAttr() || - Ivar->isUnnamedBitfield()) + Ivar->hasAttr() || Ivar->isUnnamedBitField()) continue; M[Ivar] = Unused; diff --git a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp index f7b7befe28ee7dc5076c51c359a5b9b7a592977f..19877964bd900a9c4758337b6618e273d1070769 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp @@ -129,9 +129,11 @@ static llvm::StringRef indefiniteArticleBasedOnVowel(char a) { class StdVariantChecker : public Checker { // Call descriptors to find relevant calls - CallDescription VariantConstructor{{"std", "variant", "variant"}}; - CallDescription VariantAssignmentOperator{{"std", "variant", "operator="}}; - CallDescription StdGet{{"std", "get"}, 1, 1}; + CallDescription VariantConstructor{CDM::CXXMethod, + {"std", "variant", "variant"}}; + CallDescription VariantAssignmentOperator{CDM::CXXMethod, + {"std", "variant", "operator="}}; + CallDescription StdGet{CDM::SimpleFunc, {"std", "get"}, 1, 1}; BugType BadVariantType{this, "BadVariantType", "BadVariantType"}; @@ -295,4 +297,4 @@ bool clang::ento::shouldRegisterStdVariantChecker( void clang::ento::registerStdVariantChecker(clang::ento::CheckerManager &mgr) { mgr.registerChecker(); -} \ No newline at end of file +} diff --git a/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp index 2dc9e29ca90688cf81b6a3fba1e08d79220e70c9..8f1c31763e212c31b37cf9d7eede11bce628ad38 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp @@ -27,7 +27,7 @@ class StringChecker : public Checker { mutable const FunctionDecl *StringConstCharPtrCtor = nullptr; mutable CanQualType SizeTypeTy; const CallDescription TwoParamStdStringCtor = { - {"std", "basic_string", "basic_string"}, 2, 2}; + CDM::CXXMethod, {"std", "basic_string", "basic_string"}, 2, 2}; bool isCharToStringCtor(const CallEvent &Call, const ASTContext &ACtx) const; diff --git a/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp index eae162cda6931073b0d965a8b006f30f59e28fe4..a82f7caf16b291f2b018671658fe62d044105551 100644 --- a/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp @@ -30,7 +30,7 @@ class PutenvWithAutoChecker : public Checker { private: BugType BT{this, "'putenv' function should not be called with auto variables", categories::SecurityError}; - const CallDescription Putenv{{"putenv"}, 1}; + const CallDescription Putenv{CDM::CLibrary, {"putenv"}, 1}; public: void checkPostCall(const CallEvent &Call, CheckerContext &C) const; diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 755a8c4b22fd9e907a68de2fbd3ec441ac29a8ec..ebba181eb2d842b4f05baa56d196c7d8997e02c0 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2570,7 +2570,7 @@ std::optional RegionStoreManager::tryBindSmallStruct( return std::nullopt; for (const auto *FD : RD->fields()) { - if (FD->isUnnamedBitfield()) + if (FD->isUnnamedBitField()) continue; // If there are too many fields, or if any of the fields are aggregates, @@ -2697,7 +2697,7 @@ RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B, break; // Skip any unnamed bitfields to stay in sync with the initializers. - if (FI->isUnnamedBitfield()) + if (FI->isUnnamedBitField()) continue; QualType FTy = FI->getType(); diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index e0b18120fd2110dc61ea93ef5863d96331e87d5d..5ae9b1dc7bff869ba6586737d847bc75d3c2ea67 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -233,3 +233,27 @@ _Static_assert(funcp == (void*)0, ""); // all-error {{failed due to requirement // pedantic-warning {{expression is not an integer constant expression}} _Static_assert(funcp == (void*)123, ""); // pedantic-warning {{equality comparison between function pointer and void pointer}} \ // pedantic-warning {{expression is not an integer constant expression}} + +void unaryops(void) { + (void)(++(struct x {unsigned x;}){3}.x); + (void)(--(struct y {unsigned x;}){3}.x); + (void)(++(struct z {float x;}){3}.x); + (void)(--(struct w {float x;}){3}.x); + + (void)((struct xx {unsigned x;}){3}.x++); + (void)((struct yy {unsigned x;}){3}.x--); + (void)((struct zz {float x;}){3}.x++); + (void)((struct ww {float x;}){3}.x--); +} + +/// This used to fail because we didn't properly mark the struct +/// initialized through a CompoundLiteralExpr as initialized. +struct TestStruct { + int a; + int b; +}; +int Y __attribute__((annotate( + "GlobalValAnnotationWithArgs", + 42, + (struct TestStruct) { .a = 1, .b = 2 } +))); diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 2c33fa1bf884324486947a277ebfa792da9c3994..3e52354a4a1067a84d549563f529138c4ff13640 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1317,3 +1317,16 @@ namespace { F f; static_assert(f.Z == 12, ""); } + +namespace UnnamedBitFields { + struct A { + int : 1; + double f; + int : 1; + char c; + }; + + constexpr A a = (A){1.0, 'a'}; + static_assert(a.f == 1.0, ""); + static_assert(a.c == 'a', ""); +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-cxx23.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-cxx23.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c1f30f81a01155e027a7d787e519545ec996482 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-cxx23.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s + +auto x0 = requires (this int) { true; }; // expected-error {{a requires expression cannot have an explicit object parameter}} +auto x1 = requires (int, this int) { true; }; // expected-error {{a requires expression cannot have an explicit object parameter}} + +template // expected-error {{expected template parameter}} +void f(); // expected-error {{no function template matches function template specialization 'f'}} diff --git a/clang/test/CodeGen/X86/x86-cf-protection.c b/clang/test/CodeGen/X86/x86-cf-protection.c index ba63b9e17c6f63d0929f01d70db77a4f38d3f306..84c7c0f16663c90f93cadb5227b9bf39f0d547cf 100644 --- a/clang/test/CodeGen/X86/x86-cf-protection.c +++ b/clang/test/CodeGen/X86/x86-cf-protection.c @@ -1,13 +1,20 @@ // RUN: %clang_cc1 -E -triple i386 -dM -o - -fcf-protection=return %s | FileCheck %s --check-prefix=RETURN // RUN: %clang_cc1 -E -triple i386 -dM -o - -fcf-protection=branch %s | FileCheck %s --check-prefix=BRANCH // RUN: %clang_cc1 -E -triple i386 -dM -o - -fcf-protection=full %s | FileCheck %s --check-prefix=FULL +// RUN: %clang_cc1 -E -triple=x86_64 -dM -o - -fcf-protection=none %s | FileCheck %s --check-prefix=NOTCET // RUN: not %clang_cc1 -emit-llvm-only -triple i386 -target-cpu pentium-mmx -fcf-protection=branch %s 2>&1 | FileCheck %s --check-prefix=NOCFPROT +// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=return %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTR,CFPROTNONE +// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=branch %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTB,CFPROTNONE +// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=full %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTR,CFPROTB,CFPROTNONE +// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=none %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTNONE // RETURN: #define __CET__ 2 // BRANCH: #define __CET__ 1 // FULL: #define __CET__ 3 -// CFPROT: !{i32 8, !"cf-protection-branch", i32 1} - +// NOTCET-NOT: #define __CET__ // NOCFPROT: error: option 'cf-protection=branch' cannot be specified on this target +// CFPROTR: !{i32 8, !"cf-protection-return", i32 1} +// CFPROTB: !{i32 8, !"cf-protection-branch", i32 1} +// CFPROTNONE-NOT: cf-protection- void foo() {} diff --git a/clang/test/CodeGen/debug-info-file-checksum.c b/clang/test/CodeGen/debug-info-file-checksum.c index e018dbf64fc98f2b7a09cf8483d34ba9848a62b4..2ca91d605d1c4b06d953179477fee5a0bed60639 100644 --- a/clang/test/CodeGen/debug-info-file-checksum.c +++ b/clang/test/CodeGen/debug-info-file-checksum.c @@ -1,3 +1,6 @@ +// AIX does not support -gdwarf-5. +// UNSUPPORTED: target={{.*}}-aix{{.*}} + // RUN: %clang -emit-llvm -S -g -gcodeview -x c \ // RUN: %S/Inputs/debug-info-file-checksum.c -o - | FileCheck %s // RUN: %clang -emit-llvm -S -g -gcodeview -Xclang -gsrc-hash=md5 \ diff --git a/clang/test/CodeGen/dwarf-version.c b/clang/test/CodeGen/dwarf-version.c index e63316ace69c872979fff06730c7a27ab3c21e05..258c258e5f5a26f46d8efec747bfb19abaa1aae0 100644 --- a/clang/test/CodeGen/dwarf-version.c +++ b/clang/test/CodeGen/dwarf-version.c @@ -46,8 +46,10 @@ // RUN: FileCheck %s --check-prefix=VER3 // RUN: %clang -target powerpc-ibm-aix-xcoff -gdwarf-4 -S -emit-llvm -o - %s | \ // RUN: FileCheck %s --check-prefix=VER4 -// RUN: %clang -target powerpc-ibm-aix-xcoff -gdwarf-5 -S -emit-llvm -o - %s | \ -// RUN: FileCheck %s --check-prefix=VER5 +// RUN: not %clang -target powerpc-ibm-aix-xcoff -gdwarf-5 -S -emit-llvm -o - %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=UNSUPPORTED-VER5 +// RUN: not %clang -target powerpc64-ibm-aix-xcoff -gdwarf-5 -S -emit-llvm -o - %s 2>&1| \ +// RUN: FileCheck %s --check-prefix=UNSUPPORTED-VER5 int main (void) { return 0; @@ -59,6 +61,7 @@ int main (void) { // VER3: !{i32 7, !"Dwarf Version", i32 3} // VER4: !{i32 7, !"Dwarf Version", i32 4} // VER5: !{i32 7, !"Dwarf Version", i32 5} +// UNSUPPORTED-VER5: error: unsupported option '-gdwarf-5' // NODWARF-NOT: !"Dwarf Version" // CODEVIEW: !{i32 2, !"CodeView", i32 1} diff --git a/clang/test/CodeGen/ubsan-shift-bitint.c b/clang/test/CodeGen/ubsan-shift-bitint.c index 844d5c4ad846188fc01d0d2d695df8851cac310c..af65ed60918b0884db3d2aed77a0c71dcc715781 100644 --- a/clang/test/CodeGen/ubsan-shift-bitint.c +++ b/clang/test/CodeGen/ubsan-shift-bitint.c @@ -6,14 +6,14 @@ // CHECK-LABEL: define{{.*}} i32 @test_left_variable int test_left_variable(unsigned _BitInt(5) b, unsigned _BitInt(2) e) { // CHECK: [[E_REG:%.+]] = load [[E_SIZE:i2]] - // CHECK: icmp ule [[E_SIZE]] [[E_REG]], -1 + // CHECK: icmp ule [[E_SIZE]] [[E_REG]], -1, return b << e; } // CHECK-LABEL: define{{.*}} i32 @test_right_variable int test_right_variable(unsigned _BitInt(2) b, unsigned _BitInt(3) e) { // CHECK: [[E_REG:%.+]] = load [[E_SIZE:i3]] - // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1 + // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1, return b >> e; } @@ -34,3 +34,32 @@ int test_right_literal(unsigned _BitInt(2) b) { // CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds return b >> 4uwb; } + +// CHECK-LABEL: define{{.*}} i32 @test_signed_left_variable +int test_signed_left_variable(unsigned _BitInt(15) b, _BitInt(2) e) { + // CHECK: [[E_REG:%.+]] = load [[E_SIZE:i2]] + // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1, + return b << e; +} + +// CHECK-LABEL: define{{.*}} i32 @test_signed_right_variable +int test_signed_right_variable(unsigned _BitInt(32) b, _BitInt(4) e) { + // CHECK: [[E_REG:%.+]] = load [[E_SIZE:i4]] + // CHECK: icmp ule [[E_SIZE]] [[E_REG]], 7, + return b >> e; +} + +// CHECK-LABEL: define{{.*}} i32 @test_signed_left_literal +int test_signed_left_literal(unsigned _BitInt(16) b) { + // CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds + // CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds + return b << (_BitInt(4))-2wb; +} + +// CHECK-LABEL: define{{.*}} i32 @test_signed_right_literal +int test_signed_right_literal(unsigned _BitInt(16) b) { + // CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds + // CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds + return b >> (_BitInt(4))-8wb; +} + diff --git a/clang/test/CodeGenCUDA/record-layout.cu b/clang/test/CodeGenCUDA/record-layout.cu new file mode 100644 index 0000000000000000000000000000000000000000..dd34121ccb9d36a05c9cd8ac29cbadebbfde0d23 --- /dev/null +++ b/clang/test/CodeGenCUDA/record-layout.cu @@ -0,0 +1,200 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fdump-record-layouts \ +// RUN: -emit-llvm -o %t -xhip %s 2>&1 | FileCheck %s --check-prefix=AST +// RUN: cat %t | FileCheck --check-prefixes=CHECK,HOST %s +// RUN: %clang_cc1 -fcuda-is-device -triple amdgcn-amd-amdhsa -target-cpu gfx1100 \ +// RUN: -emit-llvm -fdump-record-layouts -aux-triple x86_64-pc-windows-msvc \ +// RUN: -o %t -xhip %s | FileCheck %s --check-prefix=AST +// RUN: cat %t | FileCheck --check-prefixes=CHECK,DEV %s + +#include "Inputs/cuda.h" + +// AST: *** Dumping AST Record Layout +// AST-LABEL: 0 | struct C +// AST-NEXT: 0 | struct A (base) (empty) +// AST-NEXT: 1 | struct B (base) (empty) +// AST-NEXT: 4 | int i +// AST-NEXT: | [sizeof=8, align=4, +// AST-NEXT: | nvsize=8, nvalign=4] + +// CHECK: %struct.C = type { [4 x i8], i32 } + +struct A {}; +struct B {}; +struct C : A, B { + int i; +}; + +// AST: *** Dumping AST Record Layout +// AST-LABEL: 0 | struct I +// AST-NEXT: 0 | (I vftable pointer) +// AST-NEXT: 8 | int i +// AST-NEXT: | [sizeof=16, align=8, +// AST-NEXT: | nvsize=16, nvalign=8] + +// AST: *** Dumping AST Record Layout +// AST-LABEL: 0 | struct J +// AST-NEXT: 0 | struct I (primary base) +// AST-NEXT: 0 | (I vftable pointer) +// AST-NEXT: 8 | int i +// AST-NEXT: 16 | int j +// AST-NEXT: | [sizeof=24, align=8, +// AST-NEXT: | nvsize=24, nvalign=8] + +// CHECK: %struct.I = type { ptr, i32 } +// CHECK: %struct.J = type { %struct.I, i32 } + +// HOST: @0 = private unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr @"??_R4J@@6B@", ptr @"?f@J@@UEAAXXZ", ptr null, ptr @"?h@J@@UEAAXXZ"] }, comdat($"??_7J@@6B@") +// HOST: @1 = private unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr @"??_R4I@@6B@", ptr @_purecall, ptr null, ptr @_purecall] }, comdat($"??_7I@@6B@") +// HOST: @"??_7J@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @0, i32 0, i32 0, i32 1) +// HOST: @"??_7I@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @1, i32 0, i32 0, i32 1) + +// DEV: @_ZTV1J = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1J1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1J1hEv to ptr addrspace(1))] }, comdat, align 8 +// DEV: @_ZTV1I = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8 +struct I { + virtual void f() = 0; + __device__ virtual void g() = 0; + __device__ __host__ virtual void h() = 0; + int i; +}; + +struct J : I { + void f() override {} + __device__ void g() override {} + __device__ __host__ void h() override {} + int j; +}; + +// DEV: define dso_local amdgpu_kernel void @_Z8C_kernel1C(ptr addrspace(4) noundef byref(%struct.C) align 4 %0) +// DEV: %coerce = alloca %struct.C, align 4, addrspace(5) +// DEV: %c = addrspacecast ptr addrspace(5) %coerce to ptr +// DEV: call void @llvm.memcpy.p0.p4.i64(ptr align 4 %c, ptr addrspace(4) align 4 %0, i64 8, i1 false) +// DEV: %i = getelementptr inbounds %struct.C, ptr %c, i32 0, i32 1 +// DEV: store i32 1, ptr %i, align 4 + +__global__ void C_kernel(C c) +{ + c.i = 1; +} + +// HOST-LABEL: define dso_local void @"?test_C@@YAXXZ"() +// HOST: %c = alloca %struct.C, align 4 +// HOST: %i = getelementptr inbounds %struct.C, ptr %c, i32 0, i32 1 +// HOST: store i32 11, ptr %i, align 4 + +void test_C() { + C c; + c.i = 11; + C_kernel<<<1, 1>>>(c); +} + +// DEV: define dso_local void @_Z5J_devP1J(ptr noundef %j) +// DEV: %j.addr = alloca ptr, align 8, addrspace(5) +// DEV: %j.addr.ascast = addrspacecast ptr addrspace(5) %j.addr to ptr +// DEV: store ptr %j, ptr %j.addr.ascast, align 8 +// DEV: %0 = load ptr, ptr %j.addr.ascast, align 8 +// DEV: %i = getelementptr inbounds %struct.I, ptr %0, i32 0, i32 1 +// DEV: store i32 2, ptr %i, align 8 +// DEV: %1 = load ptr, ptr %j.addr.ascast, align 8 +// DEV: %j1 = getelementptr inbounds %struct.J, ptr %1, i32 0, i32 1 +// DEV: store i32 3, ptr %j1, align 8 +// DEV: %2 = load ptr, ptr %j.addr.ascast, align 8 +// DEV: %vtable = load ptr addrspace(1), ptr %2, align 8 +// DEV: %vfn = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %vtable, i64 1 +// DEV: %3 = load ptr addrspace(1), ptr addrspace(1) %vfn, align 8 +// DEV: call addrspace(1) void %3(ptr noundef nonnull align 8 dereferenceable(24) %2) +// DEV: %4 = load ptr, ptr %j.addr.ascast, align 8 +// DEV: %vtable2 = load ptr addrspace(1), ptr %4, align 8 +// DEV: %vfn3 = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %vtable2, i64 2 +// DEV: %5 = load ptr addrspace(1), ptr addrspace(1) %vfn3, align 8 +// DEV: call addrspace(1) void %5(ptr noundef nonnull align 8 dereferenceable(24) %4) + +__device__ void J_dev(J *j) { + j->i = 2; + j->j = 3; + j->g(); + j->h(); +} + +// DEV: define dso_local amdgpu_kernel void @_Z8J_kernelv() +// DEV: %j = alloca %struct.J, align 8, addrspace(5) +// DEV: %j.ascast = addrspacecast ptr addrspace(5) %j to ptr +// DEV: call void @_ZN1JC1Ev(ptr noundef nonnull align 8 dereferenceable(24) %j.ascast) +// DEV: call void @_Z5J_devP1J(ptr noundef %j.ascast) + +__global__ void J_kernel() { + J j; + J_dev(&j); +} + +// HOST-LABEL: define dso_local void @"?J_host@@YAXPEAUJ@@@Z"(ptr noundef %j) +// HOST: %0 = load ptr, ptr %j.addr, align 8 +// HOST: %i = getelementptr inbounds %struct.I, ptr %0, i32 0, i32 1 +// HOST: store i32 12, ptr %i, align 8 +// HOST: %1 = load ptr, ptr %j.addr, align 8 +// HOST: %j1 = getelementptr inbounds %struct.J, ptr %1, i32 0, i32 1 +// HOST: store i32 13, ptr %j1, align 8 +// HOST: %2 = load ptr, ptr %j.addr, align 8 +// HOST: %vtable = load ptr, ptr %2, align 8 +// HOST: %vfn = getelementptr inbounds ptr, ptr %vtable, i64 0 +// HOST: %3 = load ptr, ptr %vfn, align 8 +// HOST: call void %3(ptr noundef nonnull align 8 dereferenceable(24) %2) +// HOST: %4 = load ptr, ptr %j.addr, align 8 +// HOST: %vtable2 = load ptr, ptr %4, align 8 +// HOST: %vfn3 = getelementptr inbounds ptr, ptr %vtable2, i64 2 +// HOST: %5 = load ptr, ptr %vfn3, align 8 +// HOST: call void %5(ptr noundef nonnull align 8 dereferenceable(24) %4) + +void J_host(J *j) { + j->i = 12; + j->j = 13; + j->f(); + j->h(); +} + +// HOST: define dso_local void @"?test_J@@YAXXZ"() +// HOST: %j = alloca %struct.J, align 8 +// HOST: %call = call noundef ptr @"??0J@@QEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(24) %j) +// HOST: call void @"?J_host@@YAXPEAUJ@@@Z"(ptr noundef %j) + +void test_J() { + J j; + J_host(&j); + J_kernel<<<1, 1>>>(); +} + +// HOST: define linkonce_odr dso_local noundef ptr @"??0J@@QEAA@XZ"(ptr noundef nonnull returned align 8 dereferenceable(24) %this) +// HOST: %this.addr = alloca ptr, align 8 +// HOST: store ptr %this, ptr %this.addr, align 8 +// HOST: %this1 = load ptr, ptr %this.addr, align 8 +// HOST: %call = call noundef ptr @"??0I@@QEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(16) %this1) #5 +// HOST: store ptr @"??_7J@@6B@", ptr %this1, align 8 +// HOST: ret ptr %this1 + +// HOST: define linkonce_odr dso_local noundef ptr @"??0I@@QEAA@XZ"(ptr noundef nonnull returned align 8 dereferenceable(16) %this) +// HOST: %this.addr = alloca ptr, align 8 +// HOST: store ptr %this, ptr %this.addr, align 8 +// HOST: %this1 = load ptr, ptr %this.addr, align 8 +// HOST: store ptr @"??_7I@@6B@", ptr %this1, align 8 +// HOST: ret ptr %this1 + +// DEV: define linkonce_odr void @_ZN1JC1Ev(ptr noundef nonnull align 8 dereferenceable(24) %this) +// DEV: %this.addr = alloca ptr, align 8, addrspace(5) +// DEV: %this.addr.ascast = addrspacecast ptr addrspace(5) %this.addr to ptr +// DEV: store ptr %this, ptr %this.addr.ascast, align 8 +// DEV: %this1 = load ptr, ptr %this.addr.ascast, align 8 +// DEV: call void @_ZN1JC2Ev(ptr noundef nonnull align 8 dereferenceable(24) %this1) + +// DEV: define linkonce_odr void @_ZN1JC2Ev(ptr noundef nonnull align 8 dereferenceable(24) %this) +// DEV: %this.addr = alloca ptr, align 8, addrspace(5) +// DEV: %this.addr.ascast = addrspacecast ptr addrspace(5) %this.addr to ptr +// DEV: store ptr %this, ptr %this.addr.ascast, align 8 +// DEV: %this1 = load ptr, ptr %this.addr.ascast, align 8 +// DEV: call void @_ZN1IC2Ev(ptr noundef nonnull align 8 dereferenceable(16) %this1) +// DEV: store ptr addrspace(1) getelementptr inbounds inrange(-16, 24) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1J, i32 0, i32 0, i32 2), ptr %this1, align 8 + +// DEV: define linkonce_odr void @_ZN1IC2Ev(ptr noundef nonnull align 8 dereferenceable(16) %this) +// DEV: %this.addr = alloca ptr, align 8, addrspace(5) +// DEV: %this.addr.ascast = addrspacecast ptr addrspace(5) %this.addr to ptr +// DEV: store ptr %this, ptr %this.addr.ascast, align 8 +// DEV: %this1 = load ptr, ptr %this.addr.ascast, align 8 +// DEV: store ptr addrspace(1) getelementptr inbounds inrange(-16, 24) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1I, i32 0, i32 0, i32 2), ptr %this1, align 8 diff --git a/clang/test/CodeGenCXX/debug-info-alias.cpp b/clang/test/CodeGenCXX/debug-info-alias.cpp index 3d3f87ed1f6fa8835c099be0f44fb789c2e87bda..bf2dbee465959268dbbdc886fccfed7630a43cc6 100644 --- a/clang/test/CodeGenCXX/debug-info-alias.cpp +++ b/clang/test/CodeGenCXX/debug-info-alias.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -g -gno-template-alias -std=c++11 -S -emit-llvm %s -o - | FileCheck %s template struct foo { diff --git a/clang/test/CodeGenCXX/defaulted-template-alias.cpp b/clang/test/CodeGenCXX/defaulted-template-alias.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a038aa0d9dc208efc7504779a9d4ab8a3b7ad5a6 --- /dev/null +++ b/clang/test/CodeGenCXX/defaulted-template-alias.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \ +// RUN: | FileCheck %s + +//// Check that -gtemplate-alias causes DW_TAG_template_alias emission for +//// template aliases with default parameter values. See template-alias.cpp for +//// more template alias tests. +//// FIXME: We currently do not emit defaulted arguments. + +template +struct X { + char m; +}; + +template +struct Y { + char n; +}; + +template class T = Y, int I = 5, typename... Ts> +using A = X; + +//// We should be able to emit type alias metadata which describes all the +//// values, including the defaulted parameters and empty parameter pack. +A a; + +// CHECK: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]]) +// CHECK: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", +// CHECK: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// CHECK: ![[extraData]] = !{![[NonDefault:[0-9]+]]} +// CHECK: ![[NonDefault]] = !DITemplateTypeParameter(name: "NonDefault", type: ![[int]]) + +//// FIXME: Ideally, we would describe the deafulted args, like this: +// : ![[extraData]] = !{![[NonDefault:[0-9]+]], ![[T:[0-9]+]], ![[I:[0-9]+]], ![[Ts:[0-9]+]]} +// : ![[NonDefault]] = !DITemplateTypeParameter(name: "NonDefault", type: ![[int]]) +// : ![[T]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "T", defaulted: true, value: !"Y") +// : ![[I]] = !DITemplateValueParameter(name: "I", type: ![[int]], defaulted: true, value: i32 5) +// : ![[Ts]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Ts", value: ![[types:[0-9]+]]) +// : ![[types]] = !{} diff --git a/clang/test/CodeGenCXX/pragma-gcc-unroll.cpp b/clang/test/CodeGenCXX/pragma-gcc-unroll.cpp index ed75e0b6e3c364bd388fd423510b787f313abacb..8a94a5cc91e2396356d6733af6ef518071a92198 100644 --- a/clang/test/CodeGenCXX/pragma-gcc-unroll.cpp +++ b/clang/test/CodeGenCXX/pragma-gcc-unroll.cpp @@ -96,6 +96,26 @@ void template_test(double *List, int Length) { for_template_define_test(List, Length, Value); } +void for_unroll_zero_test(int *List, int Length) { + // CHECK: define {{.*}} @_Z20for_unroll_zero_testPii + #pragma GCC unroll 0 + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_14:.*]] + List[i] = i * 2; + } +} + +void while_unroll_zero_test(int *List, int Length) { + // CHECK: define {{.*}} @_Z22while_unroll_zero_testPii + int i = 0; +#pragma GCC unroll(0) + while (i < Length) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_15:.*]] + List[i] = i * 2; + i++; + } +} + // CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], ![[UNROLL_ENABLE:.*]]} // CHECK: ![[UNROLL_ENABLE]] = !{!"llvm.loop.unroll.enable"} // CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]} @@ -107,3 +127,5 @@ void template_test(double *List, int Length) { // CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_8:.*]]} // CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]]} // CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], [[MP]], ![[UNROLL_DISABLE:.*]]} +// CHECK: ![[LOOP_15]] = distinct !{![[LOOP_15]], [[MP]], ![[UNROLL_DISABLE:.*]]} diff --git a/clang/test/CodeGenCXX/template-alias.cpp b/clang/test/CodeGenCXX/template-alias.cpp new file mode 100644 index 0000000000000000000000000000000000000000..256ed693aa2fe7c55093619836688174df9d9fc7 --- /dev/null +++ b/clang/test/CodeGenCXX/template-alias.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \ +// RUN: | FileCheck %s --check-prefixes=ALIAS-SIMPLE,ALIAS-ALL + +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=mangled \ +// RUN: | FileCheck %s --check-prefixes=ALIAS-MANGLED,ALIAS-ALL + +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s \ +// RUN: | FileCheck %s --check-prefixes=ALIAS-FULL,ALIAS-ALL + +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone %s \ +// RUN: | FileCheck %s --check-prefixes=TYPEDEF + + +//// Check that -gtemplate-alias causes DW_TAG_template_alias emission for +//// template aliases, and that respects gsimple-template-names. +//// +//// Test type and value template parameters. + +template +struct X { + Y m1 = Z; +}; + +template +using A = X; + +A a; + + +// ALIAS-SIMPLE: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]]) +// ALIAS-SIMPLE: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", + +// FIXME: Mangled name is wrong (not a regression). +// ALIAS-MANGLED: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]]) +// ALIAS-MANGLED: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_STN|X|", + +// ALIAS-FULL: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]]) +// ALIAS-FULL: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", + +// ALIAS-ALL: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// ALIAS-ALL: ![[extraData]] = !{![[B:[0-9]+]], ![[C:[0-9]+]]} +// ALIAS-ALL: ![[B]] = !DITemplateTypeParameter(name: "B", type: ![[int]]) +// ALIAS-ALL: ![[C]] = !DITemplateValueParameter(name: "C", type: ![[int]], value: i32 5) + +// TYPEDEF: !DIDerivedType(tag: DW_TAG_typedef, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]]) +// TYPEDEF: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", +// TYPEDEF: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) diff --git a/clang/test/CodeGenCXX/variadic-template-alias.cpp b/clang/test/CodeGenCXX/variadic-template-alias.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4340d60aa6ad9627500f5f0face23fff4a2ea1c --- /dev/null +++ b/clang/test/CodeGenCXX/variadic-template-alias.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \ +// RUN: | FileCheck %s + +//// Check that -gtemplate-alias causes DW_TAG_template_alias emission for +//// variadic template aliases. See template-alias.cpp for more template alias +//// tests. + +template +struct X { + Y m1 = Z; +}; + +template +using A = X; + +A<5, int> a; + +// CHECK: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]]) +// CHECK: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", +// CHECK: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// CHECK: ![[extraData]] = !{![[I:[0-9]+]], ![[Ts:[0-9]+]]} +// CHECK: ![[I]] = !DITemplateValueParameter(name: "I", type: ![[int]], value: i32 5) +// CHECK: ![[Ts]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Ts", value: ![[types:[0-9]+]]) +// CHECK: ![[types]] = !{![[int_template_param:[0-9]+]]} +// CHECK: ![[int_template_param]] = !DITemplateTypeParameter(type: ![[int]]) diff --git a/clang/test/Driver/aix-toolchain-include.cpp b/clang/test/Driver/aix-toolchain-include.cpp index fbe5fb8cb8613100a0c53dc560ac51ec45d25f63..b0074bf0ba1fdbf36fac67713aa13895526fbdfc 100644 --- a/clang/test/Driver/aix-toolchain-include.cpp +++ b/clang/test/Driver/aix-toolchain-include.cpp @@ -5,24 +5,28 @@ // RUN: --target=powerpc-ibm-aix \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefixes=CHECK-INTERNAL-INCLUDE,CHECK-INTERNAL-INCLUDE-CXX %s // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=powerpc64-ibm-aix \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefixes=CHECK-INTERNAL-INCLUDE,CHECK-INTERNAL-INCLUDE-CXX %s // RUN: %clang -### -xc %s 2>&1 \ // RUN: --target=powerpc-ibm-aix \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-INTERNAL-INCLUDE %s // RUN: %clang -### -xc %s 2>&1 \ // RUN: --target=powerpc64-ibm-aix \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-INTERNAL-INCLUDE %s // CHECK-INTERNAL-INCLUDE: "-cc1" @@ -31,6 +35,7 @@ // CHECK-INTERNAL-INCLUDE-CXX: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}c++{{(/|\\\\)}}v1" // CHECK-INTERNAL-INCLUDE-CXX: "-D__LIBC_NO_CPP_MATH_OVERLOADS__" // CHECK-INTERNAL-INCLUDE: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" +// CHECK-INTERNAL-INCLUDE: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}openmp" // CHECK-INTERNAL-INCLUDE: "-internal-isystem" "[[SYSROOT]]/usr/include" // Check powerpc-ibm-aix, 32-bit/64-bit. -nostdinc option. @@ -73,6 +78,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nostdlibinc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s // RUN: %clangxx -### %s 2>&1 \ @@ -80,6 +86,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nostdlibinc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s // RUN: %clang -### -xc %s 2>&1 \ @@ -87,6 +94,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nostdlibinc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s // RUN: %clang -### -xc %s 2>&1 \ @@ -94,15 +102,17 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nostdlibinc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s // CHECK-NOSTDLIBINC-INCLUDE: "-cc1" // CHECK-NOSTDLIBINC-INCLUDE: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-NOSTDLIBINC-INCLUDE: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-NOSTDLIBINC-INCLUDE: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" +// CHECK-NOSTDLIBINC-INCLUDE: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}openmp" // CHECK-NOSTDLIBINC-INCLUDE-NOT: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}c++{{(/|\\\\)}}v1" // CHECK-NOSTDLIBINC-INCLUDE-NOT: "-D__LIBC_NO_CPP_MATH_OVERLOADS__" -// CHECK-NOSTDLIBINC-INCLUDE-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include" +// CHECK-NOSTDLIBINC-INCLUDE-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include" // Check powerpc-ibm-aix, 32-bit/64-bit. -nobuiltininc option. // RUN: %clangxx -### %s 2>&1 \ @@ -110,6 +120,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nobuiltininc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefixes=CHECK-NOBUILTININC-INCLUDE,CHECK-NOBUILTININC-INCLUDE-CXX %s // RUN: %clangxx -### %s 2>&1 \ @@ -117,6 +128,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nobuiltininc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefixes=CHECK-NOBUILTININC-INCLUDE,CHECK-NOBUILTININC-INCLUDE-CXX %s // RUN: %clang -### -xc %s 2>&1 \ @@ -124,6 +136,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nobuiltininc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOBUILTININC-INCLUDE %s // RUN: %clang -### -xc %s 2>&1 \ @@ -131,6 +144,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nobuiltininc \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOBUILTININC-INCLUDE %s // CHECK-NOBUILTININC-INCLUDE: "-cc1" @@ -139,6 +153,7 @@ // CHECK-NOBUILTININC-INCLUDE-NOT: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" // CHECK-NOBUILTININC-INCLUDE-CXX: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}c++{{(/|\\\\)}}v1" // CHECK-NOBUILTININC-INCLUDE-CXX: "-D__LIBC_NO_CPP_MATH_OVERLOADS__" +// CHECK-NOBUILTININC-INCLUDE: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}openmp" // CHECK-NOBUILTININC-INCLUDE: "-internal-isystem" "[[SYSROOT]]/usr/include" // Check powerpc-ibm-aix, 32-bit/64-bit. -nostdinc++ option. @@ -147,6 +162,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nostdinc++ \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOSTDINCXX-INCLUDE %s // RUN: %clangxx -### %s 2>&1 \ @@ -154,6 +170,7 @@ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_aix_tree \ // RUN: -nostdinc++ \ +// RUN: -fopenmp=libomp \ // RUN: | FileCheck -check-prefix=CHECK-NOSTDINCXX-INCLUDE %s // CHECK-NOSTDINCXX-INCLUDE: "-cc1" @@ -162,6 +179,7 @@ // CHECK-NOSTDINCXX-INCLUDE: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" // CHECK-NOSTDINCXX-INCLUDE-NOT: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}c++{{(/|\\\\)}}v1" // CHECK-NOSTDINCXX-INCLUDE-NOT: "-D__LIBC_NO_CPP_MATH_OVERLOADS__" +// CHECK-NOSTDINCXX-INCLUDE: "-internal-isystem" "[[SYSROOT]]{{(/|\\\\)}}opt{{(/|\\\\)}}IBM{{(/|\\\\)}}openxlCSDK{{(/|\\\\)}}include{{(/|\\\\)}}openmp" // CHECK-NOSTDINCXX-INCLUDE: "-internal-isystem" "[[SYSROOT]]/usr/include" // Check powerpc-ibm-aix, 32-bit. -stdlib=libstdc++ invokes fatal error. diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index 4d58f0fb548b5793de03e7de76e5deec422f60ee..4298657ac49f5c8e86001d4070eb94354747b76b 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -118,6 +118,7 @@ // RUN: %clang_cl /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s // RUN: %clang_cl /Fe:foo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s +// RUN: %clang_cl /Fe: foo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s // FeEXT: "-out:foo.ext" // RUN: %clang_cl /LD /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXTDLL %s @@ -270,6 +271,8 @@ // P: "-o" "cl-outputs.i" // RUN: %clang_cl /P /Fifoo -### -- %s 2>&1 | FileCheck -check-prefix=Fi1 %s +// RUN: %clang_cl /P /Fi:foo -### -- %s 2>&1 | FileCheck -check-prefix=Fi1 %s +// RUN: %clang_cl /P /Fi: foo -### -- %s 2>&1 | FileCheck -check-prefix=Fi1 %s // Fi1: "-E" // Fi1: "-o" "foo.i" @@ -302,6 +305,7 @@ // RELATIVE_OBJPATH1: "-object-file-name=a.obj" // RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fo:a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1_COLON %s +// RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fo: a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1_COLON %s // RELATIVE_OBJPATH1_COLON: "-object-file-name=a.obj" // RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fofoo/a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH2 %s diff --git a/clang/test/Driver/cl-pch.cpp b/clang/test/Driver/cl-pch.cpp index d09b177eb617def0c3f77d9bd08aea929b050e0c..cc4fc435a61c20689a15542c18878a0ef9c741ca 100644 --- a/clang/test/Driver/cl-pch.cpp +++ b/clang/test/Driver/cl-pch.cpp @@ -99,6 +99,12 @@ // /Yu /Fpout.pch => out.pch is filename // RUN: %clang_cl -Werror /Yupchfile.h /FIpchfile.h /Fpout.pch /c -### -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s +// /Yu /Fp:out.pch => out.pch is filename +// RUN: %clang_cl -Werror /Yupchfile.h /FIpchfile.h /Fp:out.pch /c -### -- %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s +// /Yu /Fp: out.pch => out.pch is filename +// RUN: %clang_cl -Werror /Yupchfile.h /FIpchfile.h /Fp: out.pch /c -### -- %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s // Use .pch file, but don't build it. // CHECK-YUFP1: -include-pch // CHECK-YUFP1: out.pch diff --git a/clang/test/Driver/compress.c b/clang/test/Driver/compress.c index 073bbe2afc8b9544f8629add20fa16e32eef1609..7d30f1eae49346951af21bd01cd2681ead6b1e52 100644 --- a/clang/test/Driver/compress.c +++ b/clang/test/Driver/compress.c @@ -1,3 +1,5 @@ +// XFAIL: system-aix + // REQUIRES: zlib // RUN: %clang -### -fintegrated-as -Wa,-compress-debug-sections -c %s 2>&1 | FileCheck -check-prefix CHECK-_COMPRESS_DEBUG_SECTIONS %s diff --git a/clang/test/Driver/debug-options-embed-source.c b/clang/test/Driver/debug-options-embed-source.c new file mode 100644 index 0000000000000000000000000000000000000000..acb00fca62ee03e8469b9b735a1199ef38c568af --- /dev/null +++ b/clang/test/Driver/debug-options-embed-source.c @@ -0,0 +1,13 @@ +// AIX does not support -gdwarf-5 which is required by -gembed-source +// UNSUPPORTED: target={{.*}}-aix{{.*}} + +// RUN: %clang -### -gdwarf-5 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_5 %s +// RUN: not %clang -### -gdwarf-2 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_2 %s +// RUN: %clang -### -gdwarf-5 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_5 %s +// RUN: %clang -### -gdwarf-2 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_2 %s +// +// GEMBED_5: "-gembed-source" +// GEMBED_2: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5' +// NOGEMBED_5-NOT: "-gembed-source" +// NOGEMBED_2-NOT: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5' +// diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index e4809511ac91a07d81a4d2a2db8ea88ac3e75d35..b209c911d1ca2b051350b998f4d0e6fe5645bf3a 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -410,16 +410,6 @@ // MACRO: "-debug-info-macro" // NOMACRO-NOT: "-debug-info-macro" // -// RUN: %clang -### -gdwarf-5 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_5 %s -// RUN: not %clang -### -gdwarf-2 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_2 %s -// RUN: %clang -### -gdwarf-5 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_5 %s -// RUN: %clang -### -gdwarf-2 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_2 %s -// -// GEMBED_5: "-gembed-source" -// GEMBED_2: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5' -// NOGEMBED_5-NOT: "-gembed-source" -// NOGEMBED_2-NOT: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5' -// // RUN: %clang -### -g -fno-eliminate-unused-debug-types -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=DEBUG_UNUSED_TYPES %s // DEBUG_UNUSED_TYPES: "-debug-info-kind=unused-types" @@ -465,3 +455,13 @@ // MANGLED_TEMP_NAMES: error: unknown argument '-gsimple-template-names=mangled'; did you mean '-Xclang -gsimple-template-names=mangled' // 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). +// 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-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 +// RUN: %clang -### -target x86_64 -c -gdwarf-5 -gtemplate-alias -gno-template-alias %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS +// TEMPLATE-ALIAS: "-gtemplate-alias" +// NO-TEMPLATE-ALIAS-NOT: "-gtemplate-alias" diff --git a/clang/test/Driver/response-file-errs.c b/clang/test/Driver/response-file-errs.c index b78c86f4bdd5d20aa4463a2bedb0bb6061a3f9a2..efde7575a51e06ecd468da9d76f6edea7ea69206 100644 --- a/clang/test/Driver/response-file-errs.c +++ b/clang/test/Driver/response-file-errs.c @@ -1,6 +1,3 @@ -// AIX reacts on opening directory differently than other systems. -// XFAIL: system-aix - // If response file does not exist, '@file; directive remains unexpanded in // command line. // diff --git a/clang/test/InstallAPI/alias_list.test b/clang/test/InstallAPI/alias_list.test new file mode 100644 index 0000000000000000000000000000000000000000..3e12221e088c4b7c80ceba8b49ef6d823735a3e0 --- /dev/null +++ b/clang/test/InstallAPI/alias_list.test @@ -0,0 +1,461 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: yaml2obj %t/AliasList.yaml -o %t/Frameworks/AliasList.framework/AliasList + +; RUN: clang-installapi --target=x86_64-apple-macos13 \ +; RUN: -alias_list %t/aliases.txt \ +; RUN: -install_name /System/Library/Frameworks/AliasList.framework/Versions/A/AliasList \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F%t/Frameworks -ObjC %t/inputs.json --verify-mode=Pedantic \ +; RUN: --verify-against=%t/Frameworks/AliasList.framework/AliasList \ +; RUN: -o %t/AliasList.tbd 2>&1 | FileCheck -allow-empty %s \ +; RUN: --implicit-check-not=error --implicit-check-not=warning +; RUN: llvm-readtapi -compare %t/expected.tbd %t/AliasList.tbd + +// Check error handling. +; RUN: not clang-installapi --target=x86_64-apple-macos13 \ +; RUN: -alias_list %t/invalid.txt \ +; RUN: -install_name /System/Library/Frameworks/AliasList.framework/Versions/A/AliasList \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F%t/Frameworks -ObjC %t/inputs.json --verify-mode=Pedantic \ +; RUN: --verify-against=%t/Frameworks/AliasList.framework/AliasList \ +; RUN: -o %t/AliasList.tbd 2>&1 | FileCheck -allow-empty %s \ +; RUN: --check-prefix=INVALID + +; INVALID: error: could not read alias list {{.*}} missing alias for: _hidden + +;--- Frameworks/AliasList.framework/Headers/AliasList.h +// simple alias from one symbol to another. +extern int simple_symbol; +extern int alias_symbol; + +// This symbol comes from the alias file. +extern int exported_symbol; + +// This symbol was moved here and has several special hide symbols in the alias +// file. +extern int moved_here_symbol; + +// This alias is public, whereas the source is private. +extern int public_symbol; + +;--- Frameworks/AliasList.framework/PrivateHeaders/AliasList_Private.h +// This is a private symbol that has a public alias. +extern int private_symbol; + +;--- aliases.txt +# comment +_simple_symbol _alias_symbol +# test multiple space characters separated symbol and alias +_hidden_symbol _exported_symbol # test inline comment with spaces +# test tab character separated symbol and alias +_moved_here_symbol $ld$hide$os10.4$_moved_here_symbol# test inline comment without spaces +# test trailing space character +_moved_here_symbol $ld$hide$os10.5$_moved_here_symbol +# test trailing tab character +_moved_here_symbol $ld$hide$os10.6$_moved_here_symbol +_private_symbol _public_symbol + +;--- invalid.txt +# comment +_simple_symbol _alias_symbol +_hidden # no matching + +;--- expected.tbd +{ + "main_library": { + "exported_symbols": [ + { + "data": { + "global": [ + "_exported_symbol", "_simple_symbol", "_moved_here_symbol", + "$ld$hide$os10.6$_moved_here_symbol", "$ld$hide$os10.4$_moved_here_symbol", + "$ld$hide$os10.5$_moved_here_symbol", "_public_symbol", + "_private_symbol", "_alias_symbol" + ] + } + } + ], + "flags": [ + { + "attributes": [ + "not_app_extension_safe" + ] + } + ], + "install_names": [ + { + "name": "/System/Library/Frameworks/AliasList.framework/Versions/A/AliasList" + } + ], + "target_info": [ + { + "min_deployment": "13", + "target": "x86_64-macos" + } + ] + }, + "tapi_tbd_version": 5 +} + +;--- AliasList.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 13 + sizeofcmds: 920 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __TEXT + vmaddr: 0 + vmsize: 4096 + fileoff: 0 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xBB8 + size: 0 + offset: 0xBB8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA_CONST + vmaddr: 4096 + vmsize: 4096 + fileoff: 4096 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 16 + Sections: + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x1000 + size: 8 + offset: 0x1000 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 8192 + vmsize: 4096 + fileoff: 8192 + filesize: 0 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __common + segname: __DATA + addr: 0x2000 + size: 40 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 12288 + vmsize: 672 + fileoff: 8192 + filesize: 672 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 8192 + export_size: 248 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 8448 + nsyms: 11 + stroff: 8624 + strsize: 240 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 1 + iextdefsym: 1 + nextdefsym: 9 + iundefsym: 10 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/AliasList.framework/Versions/A/AliasList' + ZeroPadBytes: 5 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4468-5555-3144-A123-B0FDB87F9813 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 8440 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 8448 + datasize: 0 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 21 + Name: '$ld$hide$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 89 + Name: '4$_moved_here_symbol' + Flags: 0x0 + Address: 0x2000 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 94 + Name: '6$_moved_here_symbol' + Flags: 0x0 + Address: 0x2008 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 99 + Name: '5$_moved_here_symbol' + Flags: 0x0 + Address: 0x2004 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 104 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 179 + Name: alias_symbol + Flags: 0x0 + Address: 0x2024 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 184 + Name: p + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 217 + Name: ublic_symbol + Flags: 0x0 + Address: 0x2020 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 222 + Name: rivate_symbol + Flags: 0x0 + Address: 0x2018 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 227 + Name: simple_symbol + Flags: 0x0 + Address: 0x200C + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 232 + Name: moved_here_symbol + Flags: 0x0 + Address: 0x2014 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 237 + Name: exported_symbol + Flags: 0x0 + Address: 0x201C + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 122 + n_type: 0x1E + n_sect: 3 + n_desc: 0 + n_value: 8208 + - n_strx: 2 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8192 + - n_strx: 37 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8196 + - n_strx: 72 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8200 + - n_strx: 107 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8204 + - n_strx: 137 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8212 + - n_strx: 156 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8216 + - n_strx: 172 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8220 + - n_strx: 189 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8224 + - n_strx: 204 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 8228 + - n_strx: 218 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - ' ' + - '$ld$hide$os10.4$_moved_here_symbol' + - '$ld$hide$os10.5$_moved_here_symbol' + - '$ld$hide$os10.6$_moved_here_symbol' + - _simple_symbol + - _hidden_symbol + - _moved_here_symbol + - _private_symbol + - _exported_symbol + - _public_symbol + - _alias_symbol + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' +... + +;--- inputs.json.in +{ + "headers": [ + { + "path" : "DSTROOT/Frameworks/AliasList.framework/Headers/AliasList.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/AliasList.framework/PrivateHeaders/AliasList_Private.h", + "type" : "private" + } + ], + "version": "3" +} diff --git a/clang/test/InstallAPI/binary-attributes.test b/clang/test/InstallAPI/binary-attributes.test index d97c7a14a98d7895b6f433cbd955acb3bcae0f32..b28e99f64454620e994d8e90504b94033255e7a1 100644 --- a/clang/test/InstallAPI/binary-attributes.test +++ b/clang/test/InstallAPI/binary-attributes.test @@ -43,7 +43,7 @@ ; RUN: -current_version 1.2.3 -compatibility_version 1 \ ; RUN: -allowable_client Foo -allowable_client Bar \ ; RUN: -o tmp.tbd --verify-against=%t/Simple 2>&1 | FileCheck -check-prefix=ALLOWABLE %s -; ALLOWABLE: error: allowable client missing from binary file: 'Foo [ x86_64 ]' +; ALLOWABLE: error: allowable client missing from binary file: '{{Foo|Bar}} [ x86_64 ]' ; RUN: not clang-installapi -target x86_64-apple-macos10.12 \ ; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ diff --git a/clang/test/InstallAPI/mismatching-objc-class-symbols.test b/clang/test/InstallAPI/mismatching-objc-class-symbols.test index 3b4acf1035ace382956431fcd944a2cf49ba1e08..ee35f81c58b3caa6964fb62d8a3cc66957728f7f 100644 --- a/clang/test/InstallAPI/mismatching-objc-class-symbols.test +++ b/clang/test/InstallAPI/mismatching-objc-class-symbols.test @@ -19,7 +19,7 @@ ; RUN: llvm-readtapi -compare %t/mismatching.tbd %t/mismatching-expected.tbd // Try out a dylib that only has 1 symbol for a ObjCClass, but is represented in header. -; RUN: clang-installapi -target arm64-apple-macos14 \ +; RUN: clang-installapi -target arm64-apple-macos14 -dynamiclib \ ; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ ; RUN: -I%t/usr/include %t/inputs.json -o %t/matching.tbd \ ; RUN: --verify-mode=Pedantic \ diff --git a/clang/test/InstallAPI/rpath.test b/clang/test/InstallAPI/rpath.test index 083a15419abaab04594b4aaa2c638ecb7a636cb7..ace9c47b6e686a1922ab13926f31331e2691678d 100644 --- a/clang/test/InstallAPI/rpath.test +++ b/clang/test/InstallAPI/rpath.test @@ -12,8 +12,8 @@ ; RUN: --verify-mode=Pedantic 2>&1 | FileCheck %s --check-prefix=MISSING ; RUN: llvm-readtapi --compare %t/RPath_warnings.tbd %t/expected_no_rpaths.tbd -; MISSING: warning: runpath search paths missing from installAPI option: '@loader_path/../../../SharedFrameworks/ [ x86_64 arm64 ]' -; MISSING: warning: runpath search paths missing from installAPI option: '@loader_path/../../PrivateFrameworks/ [ x86_64 arm64 ]' +; MISSING-DAG: warning: runpath search paths missing from installAPI option: '@loader_path/../../../SharedFrameworks/ [ x86_64 arm64 ]' +; MISSING-DAG: warning: runpath search paths missing from installAPI option: '@loader_path/../../PrivateFrameworks/ [ x86_64 arm64 ]' ; RUN: clang-installapi --filetype=tbd-v5 \ ; RUN: -target arm64-apple-macos13.0 -target x86_64-apple-macos13.0 \ diff --git a/clang/test/Modules/pr85122.cppm b/clang/test/Modules/pr85122.cppm new file mode 100644 index 0000000000000000000000000000000000000000..a4c89f13711a36a7160e4389060036ad1d6403a8 --- /dev/null +++ b/clang/test/Modules/pr85122.cppm @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++20 %s -Wall -fsyntax-only -verify + +// expected-no-diagnostics +export module a; + +export constexpr auto a = []{}; diff --git a/clang/test/Modules/reduced-bmi-empty-module-purview-std.cppm b/clang/test/Modules/reduced-bmi-empty-module-purview-std.cppm new file mode 100644 index 0000000000000000000000000000000000000000..3146fda3555fdfa700602a01fa6fa7126cfe4f65 --- /dev/null +++ b/clang/test/Modules/reduced-bmi-empty-module-purview-std.cppm @@ -0,0 +1,27 @@ +// Test that we won't write additional information from std namespace by default +// into the Reduced BMI if the module purview is empty. +// +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm +// RUN: llvm-bcanalyzer --dump --disable-histogram --show-binary-blobs %t/A.pcm > %t/A.dump +// RUN: cat %t/A.dump | FileCheck %t/A.cppm + +//--- std.h +namespace std { + typedef decltype(sizeof(0)) size_t; + enum class align_val_t : std::size_t {}; + + class bad_alloc { }; +} + +//--- A.cppm +module; +#include "std.h" +export module A; + +// CHECK-NOT: %t/A.dump +// RUN: cat %t/A.dump | FileCheck %t/A.cppm +// +// RUN: %clang_cc1 -std=c++20 %t/A1.cppm -emit-reduced-module-interface -o %t/A1.pcm \ +// RUN: -fmodule-file=M=%t/M.pcm +// RUN: llvm-bcanalyzer --dump --disable-histogram --show-binary-blobs %t/A1.pcm > %t/A1.dump +// RUN: cat %t/A1.dump | FileCheck %t/A1.cppm + +//--- foo.h +namespace ns { +template +class A { + +}; + +extern template class A; + +inline A a() { return A(); } +template +A _av_ = A(); + +auto _av_1 = _av_; +auto _av_2 = _av_; + +template <> +class A { + +}; + +void func(A, ...) { + +} + +} + +struct S { + union { + unsigned int V; + struct { + int v1; + int v2; + ns::A a1; + } WESQ; + }; + + union { + double d; + struct { + int v1; + unsigned v2; + ns::A a1; + } Another; + }; +}; + +//--- M.cppm +module; +#include "foo.h" +export module M; +export namespace nv { + using ns::A; + using ns::a; + using ns::_av_; + + using ns::func; +} +using ::S; + +//--- A.cppm +module; +#include "foo.h" +export module A; +import M; + +// CHECK-NOT: %t/S.dump +// RUN: cat %t/S.dump | FileCheck %s + +export module S; +static int static_func() { + return 43; +} + +export int func() { + return static_func(); +} + +// CHECK: using foo = struct foo { // expected-error {{'foo' cannot be defined in a type alias template}} + T size = 0; +}; +foo a; diff --git a/clang/test/SemaCXX/aarch64-sve-resolve-type.cpp b/clang/test/SemaCXX/aarch64-sve-resolve-type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a563848cdcf98bf3f00dbfd9dc241dc3f1f043d --- /dev/null +++ b/clang/test/SemaCXX/aarch64-sve-resolve-type.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fsyntax-only %s + +// REQUIRES: aarch64-registered-target || arm-registered-target + +// expected-no-diagnostics + +struct a {}; +__SVFloat32_t b(a); +template using e = decltype(b(c())); +e f(a); +template using h = decltype(f(c())); +template struct i { + static void j() { + a d; + g()(d); + } +}; +struct k { + template void operator()(c) { + [](h) {}; + } + void l() { i::j; } +}; diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0b2cec095c97fd62d541fd04706479f475ef855 --- /dev/null +++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +// Test that the exclude_from_explicit_instantiation attribute is ignored +// for local classes and members thereof. + +#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) // expected-note 0+{{expanded from macro}} + +namespace N0 { + + template + void f() { + struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION A { // expected-warning {{attribute ignored on local class}} + // expected-note@-1 2{{in instantiation of}} + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void g(T t) { // expected-warning {{attribute ignored on local class member}} + *t; // expected-error {{indirection requires pointer operand ('int' invalid)}} + } + + struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION B { // expected-warning {{attribute ignored on local class}} + void h(T t) { + *t; // expected-error {{indirection requires pointer operand ('int' invalid)}} + } + }; + }; + } + + template void f(); // expected-note 2{{in instantiation of}} + +} + +// This is a reduced example from libc++ which required that 'value' +// be prefixed with 'this->' because the definition of 'Local::operator A' +// was not instantiated when the definition of 'g' was. +namespace N1 { + + struct A { }; + + struct B { + operator A() { + return A(); + } + }; + + template + auto f(T t) { + return A(t); + } + + template + auto g(T t) { + struct Local { + T value; + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION // expected-warning {{attribute ignored on local class member}} + operator A() { + return A(value); + } + }; + + return f(Local(t)); + } + + auto x = g(B()); + +} diff --git a/clang/test/SemaCXX/builtins.cpp b/clang/test/SemaCXX/builtins.cpp index 567094c94c171b85439f8353ded1975a89398c40..080b4476c7eec104ded6540ca8791e1cbdd27fe8 100644 --- a/clang/test/SemaCXX/builtins.cpp +++ b/clang/test/SemaCXX/builtins.cpp @@ -76,6 +76,11 @@ using ConstMemFnType = int (Dummy::*)() const; void foo() {} +void test_builtin_empty_parentheses_diags() { + __is_trivially_copyable(); // expected-error {{expected a type}} + __is_trivially_copyable(1); // expected-error {{expected a type}} +} + void test_builtin_launder_diags(void *vp, const void *cvp, FnType *fnp, MemFnType mfp, ConstMemFnType cmfp, int (&Arr)[5]) { __builtin_launder(vp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}} diff --git a/clang/test/SemaCXX/cxx11-attr-print.cpp b/clang/test/SemaCXX/cxx11-attr-print.cpp index a169d1b4409b4dbbf117fd3dcf3298cfe672640e..2b084018bc066223e580b58fe2f60e33af50aa22 100644 --- a/clang/test/SemaCXX/cxx11-attr-print.cpp +++ b/clang/test/SemaCXX/cxx11-attr-print.cpp @@ -87,3 +87,8 @@ template struct S; // CHECK: using Small2 {{\[}}[gnu::mode(byte)]] = int; using Small2 [[gnu::mode(byte)]] = int; + +class FinalNonTemplate final {}; +// CHECK: class FinalNonTemplate final { +template class FinalTemplate final {}; +// CHECK: template class FinalTemplate final { diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index b71cd46f884d6375b0597280280e726835d08a36..6f04264a655ad5376081203ee14e408ed25c13d7 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -279,3 +279,13 @@ Bar t = Foo>(); Bar s = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of}} } // namespace test20 + +namespace test21 { +template +struct Array { const T member[N]; }; +template +using String = Array; + +// Verify no crash on constructing the aggregate deduction guides. +String s("hello"); +} // namespace test21 diff --git a/clang/test/SemaCXX/deprecated-builtins.cpp b/clang/test/SemaCXX/deprecated-builtins.cpp index 849b9b014fff25e921fbf258324721e7c54b26d3..fafc1da4da13eb8f828c8de2057647e04736dfeb 100644 --- a/clang/test/SemaCXX/deprecated-builtins.cpp +++ b/clang/test/SemaCXX/deprecated-builtins.cpp @@ -17,3 +17,8 @@ void f() { a = __has_trivial_destructor(A); // expected-warning-re {{__has_trivial_destructor {{.*}} use __is_trivially_destructible}} } + +void test_builtin_empty_parentheses_diags(void) { + __has_nothrow_copy(); // expected-error {{expected a type}} + __has_nothrow_copy(1); // expected-error {{expected a type}} +} diff --git a/clang/test/SemaCXX/explicit.cpp b/clang/test/SemaCXX/explicit.cpp index ba2c36d99daf6236634ae14c6cc56f761da60fe5..3bb04a4d62e6c855cedf8f2ea5de81c4ac371899 100644 --- a/clang/test/SemaCXX/explicit.cpp +++ b/clang/test/SemaCXX/explicit.cpp @@ -266,3 +266,18 @@ namespace PR18777 { struct S { explicit operator bool() const; } s; int *p = new int(s); // expected-error {{no viable conversion}} } + +namespace DoubleDiags { + struct ExplicitConvert{ + explicit operator int();//#DOUBLE_DIAG_OP_INT + } EC; + template + void Template(){ + // expected-error@+2{{switch condition type 'struct ExplicitConvert' requires explicit conversion to 'int'}} + // expected-note@#DOUBLE_DIAG_OP_INT{{conversion to integral type 'int'}} + switch(EC){} + }; + void Inst() { + Template(); + } +} diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl index 7e79ae3bf005fccef670103b4f18622195468a7b..b1a15c43191829a59d2d35d160c83f939be0ef7e 100644 --- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl @@ -6,11 +6,11 @@ typedef vector float3; RWBuffer Buffer; // expected-error@+2 {{class template 'RWBuffer' requires template arguments}} -// expected-note@*:* {{template declaration from hidden source: template class RWBuffer final}} +// expected-note@*:* {{template declaration from hidden source: template class RWBuffer}} RWBuffer BufferErr1; // expected-error@+2 {{too few template arguments for class template 'RWBuffer'}} -// expected-note@*:* {{template declaration from hidden source: template class RWBuffer final}} +// expected-note@*:* {{template declaration from hidden source: template class RWBuffer}} RWBuffer<> BufferErr2; [numthreads(1,1,1)] diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h index a28532e5d71668f5f88354ba4c5df6200859e332..5ff974af57f49b9ab0ed6d5c99d2778c7beb05cc 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h @@ -5,3 +5,7 @@ void f1(int * _Nonnull); void f2(Smart); // OK, not required on smart-pointer types using Alias = Smart; void f3(Alias); + +template class _Nullable SmartTmpl; +void f2(SmartTmpl); +template void f2(SmartTmpl); diff --git a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..889025c26818d844e55fff15de6f6574a2fa4268 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp @@ -0,0 +1,304 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER + +int some_int(); +short some_short(); +long some_long(); +enum E{}; +E some_enum(); + +struct CorrectConvert { + operator int(); +} Convert; + + +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_workers(some_int()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers 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 + +#pragma acc kernels num_workers(some_short()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // 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 parallel num_workers(some_long()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CallExpr{{.*}}'long' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'long (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'long ()' lvalue Function{{.*}} 'some_long' 'long ()' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_workers(some_enum()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CallExpr{{.*}}'E' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'E (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'E ()' lvalue Function{{.*}} 'some_enum' 'E ()' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels num_workers(Convert) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'int' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator int + // CHECK-NEXT: DeclRefExpr{{.*}} 'struct CorrectConvert':'CorrectConvert' lvalue Var + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels vector_length(some_short()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: vector_length clause + // 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 +} + +template +void TemplUses(T t, U u) { + // CHECK-NEXT: FunctionTemplateDecl + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}typename depth 0 index 0 T + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}typename depth 0 index 1 U + // CHECK-NEXT: FunctionDecl{{.*}} TemplUses 'void (T, U)' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced t 'T' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced u 'U' + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_workers(t) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'T' lvalue ParmVar{{.*}} 't' 'T' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels num_workers(u) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_workers(U::value) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels num_workers(T{}) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'T' 'T' list + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_workers(U{}) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'U' 'U' list + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels num_workers(typename U::IntTy{}) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename U::IntTy' 'typename U::IntTy' list + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_workers(typename U::ShortTy{}) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename U::ShortTy' 'typename U::ShortTy' list + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels vector_length(u) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: vector_length clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel vector_length(U::value) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: vector_length clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // Check the instantiated versions of the above. + // CHECK-NEXT: FunctionDecl{{.*}} used TemplUses 'void (CorrectConvert, HasInt)' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'CorrectConvert' + // CHECK-NEXT: RecordType{{.*}} 'CorrectConvert' + // CHECK-NEXT: CXXRecord{{.*}} 'CorrectConvert' + // CHECK-NEXT: TemplateArgument type 'HasInt' + // CHECK-NEXT: RecordType{{.*}} 'HasInt' + // CHECK-NEXT: CXXRecord{{.*}} 'HasInt' + // CHECK-NEXT: ParmVarDecl{{.*}} used t 'CorrectConvert' + // CHECK-NEXT: ParmVarDecl{{.*}} used u 'HasInt' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'int' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator int + // CHECK-NEXT: DeclRefExpr{{.*}} 'CorrectConvert' lvalue ParmVar + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers 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_workers clause + // 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: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'int' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator int + // CHECK-NEXT: MaterializeTemporaryExpr{{.*}} 'CorrectConvert' lvalue + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'CorrectConvert' functional cast to struct CorrectConvert + // CHECK-NEXT: InitListExpr{{.*}}'CorrectConvert' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: ExprWithCleanups + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'char' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'char' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator char + // CHECK-NEXT: MaterializeTemporaryExpr{{.*}} 'HasInt' lvalue + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'HasInt' functional cast to struct HasInt + // CHECK-NEXT: InitListExpr{{.*}}'HasInt' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: ExprWithCleanups + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename struct HasInt::IntTy + // CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::IntTy':'int' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_workers clause + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename struct HasInt::ShortTy + // CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::ShortTy':'short' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: vector_length 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: vector_length clause + // 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 +} + +struct HasInt { + using IntTy = int; + using ShortTy = short; + static constexpr int value = 1; + + operator char(); +}; + +void Inst() { + TemplUses({}, {}); +} +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/compute-construct-num_workers-clause.c b/clang/test/SemaOpenACC/compute-construct-num_workers-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..19e247a2f810ae5d4a9fca33f73b4229786d71ec --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-num_workers-clause.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +short getS(); + +void Test() { +#pragma acc parallel num_workers(1) + while(1); +#pragma acc kernels num_workers(1) + while(1); + + // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'serial' directive}} +#pragma acc serial num_workers(1) + while(1); + + struct NotConvertible{} NC; + // expected-error@+1{{OpenACC clause 'num_workers' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_workers(NC) + while(1); + +#pragma acc kernels num_workers(getS()) + while(1); + + struct Incomplete *SomeIncomplete; + + // expected-error@+1{{OpenACC clause 'num_workers' requires expression of integer type ('struct Incomplete' invalid)}} +#pragma acc kernels num_workers(*SomeIncomplete) + while(1); + + enum E{A} SomeE; + +#pragma acc kernels num_workers(SomeE) + while(1); +} diff --git a/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp b/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9449b77d092f4ad219c61d7c8a248dd6443731bf --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp @@ -0,0 +1,133 @@ +// 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; + +void Test() { +#pragma acc parallel num_workers(1) + while(1); +#pragma acc kernels num_workers(1) + while(1); + + // expected-error@+1{{OpenACC clause 'num_workers' requires expression of integer type ('struct NotConvertible' invalid}} +#pragma acc parallel num_workers(NC) + while(1); + + // expected-error@+2{{OpenACC integer expression has incomplete class type 'struct Incomplete'}} + // expected-note@#INCOMPLETE{{forward declaration of 'Incomplete'}} +#pragma acc kernels num_workers(*SomeIncomplete) + while(1); + +#pragma acc parallel num_workers(SomeE) + while(1); + + // expected-error@+1{{OpenACC clause 'num_workers' requires expression of integer type ('enum E2' invalid}} +#pragma acc kernels num_workers(SomeE2) + while(1); + +#pragma acc parallel num_workers(Convert) + while(1); + + // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc kernels num_workers(Explicit) + 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_workers(Ambiguous) + while(1); +} + +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@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel num_workers(HasInt::Invalid) + while (1); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-note@#INST{{in instantiation of function template specialization 'TestInst' requested here}} +#pragma acc kernels num_workers(T::Invalid) + while (1); + + // expected-error@+3{{multiple conversions from expression type 'const 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_workers(HasInt::ACValue) + while (1); + + // expected-error@+3{{multiple conversions from expression type 'const 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 kernels num_workers(T::ACValue) + while (1); + + // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc parallel num_workers(HasInt::EXValue) + while (1); + + // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc kernels num_workers(T::EXValue) + while (1); + +#pragma acc parallel num_workers(HasInt::value) + while (1); + +#pragma acc kernels num_workers(T::value) + while (1); + +#pragma acc parallel num_workers(HasInt::IntTy{}) + while (1); + +#pragma acc kernels num_workers(typename T::ShortTy{}) + while (1); + +#pragma acc parallel num_workers(HasInt::IntTy{}) + while (1); + +#pragma acc kernels num_workers(typename T::ShortTy{}) + while (1); + + HasInt HI{}; + T MyT{}; + +#pragma acc parallel num_workers(HI) + while (1); + +#pragma acc kernels num_workers(MyT) + while (1); +} + +void Inst() { + TestInst(); // #INST +} diff --git a/clang/test/SemaOpenACC/compute-construct-vector_length-clause.c b/clang/test/SemaOpenACC/compute-construct-vector_length-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..cd85bdefb602d3d0b97073b508e0ad997ee1bf2e --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-vector_length-clause.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +short getS(); + +void Test() { +#pragma acc parallel vector_length(1) + while(1); +#pragma acc kernels vector_length(1) + while(1); + + // expected-error@+1{{OpenACC 'vector_length' clause is not valid on 'serial' directive}} +#pragma acc serial vector_length(1) + while(1); + + struct NotConvertible{} NC; + // expected-error@+1{{OpenACC clause 'vector_length' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel vector_length(NC) + while(1); + +#pragma acc kernels vector_length(getS()) + while(1); + + struct Incomplete *SomeIncomplete; + + // expected-error@+1{{OpenACC clause 'vector_length' requires expression of integer type ('struct Incomplete' invalid)}} +#pragma acc kernels vector_length(*SomeIncomplete) + while(1); + + enum E{A} SomeE; + +#pragma acc kernels vector_length(SomeE) + while(1); +} diff --git a/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp b/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6c5dde1a02355b8f4ed0b489ef8e1afc61e9da7 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp @@ -0,0 +1,133 @@ +// 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; + +void Test() { +#pragma acc parallel vector_length(1) + while(1); +#pragma acc kernels vector_length(1) + while(1); + + // expected-error@+1{{OpenACC clause 'vector_length' requires expression of integer type ('struct NotConvertible' invalid}} +#pragma acc parallel vector_length(NC) + while(1); + + // expected-error@+2{{OpenACC integer expression has incomplete class type 'struct Incomplete'}} + // expected-note@#INCOMPLETE{{forward declaration of 'Incomplete'}} +#pragma acc kernels vector_length(*SomeIncomplete) + while(1); + +#pragma acc parallel vector_length(SomeE) + while(1); + + // expected-error@+1{{OpenACC clause 'vector_length' requires expression of integer type ('enum E2' invalid}} +#pragma acc kernels vector_length(SomeE2) + while(1); + +#pragma acc parallel vector_length(Convert) + while(1); + + // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc kernels vector_length(Explicit) + 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 vector_length(Ambiguous) + while(1); +} + +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@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel vector_length(HasInt::Invalid) + while (1); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-note@#INST{{in instantiation of function template specialization 'TestInst' requested here}} +#pragma acc kernels vector_length(T::Invalid) + while (1); + + // expected-error@+3{{multiple conversions from expression type 'const 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 vector_length(HasInt::ACValue) + while (1); + + // expected-error@+3{{multiple conversions from expression type 'const 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 kernels vector_length(T::ACValue) + while (1); + + // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc parallel vector_length(HasInt::EXValue) + while (1); + + // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc kernels vector_length(T::EXValue) + while (1); + +#pragma acc parallel vector_length(HasInt::value) + while (1); + +#pragma acc kernels vector_length(T::value) + while (1); + +#pragma acc parallel vector_length(HasInt::IntTy{}) + while (1); + +#pragma acc kernels vector_length(typename T::ShortTy{}) + while (1); + +#pragma acc parallel vector_length(HasInt::IntTy{}) + while (1); + +#pragma acc kernels vector_length(typename T::ShortTy{}) + while (1); + + HasInt HI{}; + T MyT{}; + +#pragma acc parallel vector_length(HI) + while (1); + +#pragma acc kernels vector_length(MyT) + while (1); +} + +void Inst() { + TestInst(); // #INST +} diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index fd71aaec59435b25d82f9c2154b3a1636a16b934..add28ab4fcda2085620c34c216fbeb3a567c5bcb 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -147,7 +147,7 @@ static bool run(ArrayRef Args, const char *ProgName) { return EXIT_FAILURE; // Assign attributes for serialization. - InterfaceFile IF(Ctx.Verifier->getExports()); + InterfaceFile IF(Ctx.Verifier->takeExports()); // Assign attributes that are the same per slice first. for (const auto &TargetInfo : Opts.DriverOpts.Targets) { IF.addTarget(TargetInfo.first); diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 3dc61476ce09d919a7d7279a4bf495989ff95a62..191e944ae91e036ea2d8c17f8019da19587f019f 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -261,6 +261,11 @@ bool Options::processLinkerOptions(InputArgList &Args) { LinkerOpts.IsDylib = Args.hasArg(drv::OPT_dynamiclib); + for (auto *Arg : Args.filtered(drv::OPT_alias_list)) { + LinkerOpts.AliasLists.emplace_back(Arg->getValue()); + Arg->claim(); + } + LinkerOpts.AppExtensionSafe = Args.hasFlag( drv::OPT_fapplication_extension, drv::OPT_fno_application_extension, /*Default=*/LinkerOpts.AppExtensionSafe); @@ -684,6 +689,23 @@ InstallAPIContext Options::createContext() { return Ctx; Ctx.Reexports = Reexports; + // Collect symbols from alias lists. + AliasMap Aliases; + for (const StringRef ListPath : LinkerOpts.AliasLists) { + auto Buffer = FM->getBufferForFile(ListPath); + if (auto Err = Buffer.getError()) { + Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); + return Ctx; + } + Expected Result = parseAliasList(Buffer.get()); + if (!Result) { + Diags->Report(diag::err_cannot_read_alias_list) + << ListPath << toString(Result.takeError()); + return Ctx; + } + Aliases.insert(Result.get().begin(), Result.get().end()); + } + // Attempt to find umbrella headers by capturing framework name. StringRef FrameworkName; if (!LinkerOpts.IsDylib) @@ -849,7 +871,7 @@ InstallAPIContext Options::createContext() { } Ctx.Verifier = std::make_unique( - std::move(*Slices), std::move(ReexportedIFs), Diags, + std::move(*Slices), std::move(ReexportedIFs), std::move(Aliases), Diags, DriverOpts.VerifyMode, DriverOpts.Zippered, DriverOpts.Demangle, DriverOpts.DSYMPath); return Ctx; diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index 984366c94e91cea0eed0ca64398d83e71a10b352..e9ac75889ad30cccaab37b9e7782cfee1309ec10 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -107,6 +107,9 @@ struct LinkerOptions { /// \brief Additional library search paths. PathSeq LibPaths; + /// \brief List of alias symbol files. + PathSeq AliasLists; + /// \brief The install name to use for the dynamic library. std::string InstallName; diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 2ef599d2cd26fa94df4cf8aa7642613b36bacabf..cbc1d85bb33dfc39048a04a57095c4b96b53f103 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2795,6 +2795,14 @@ void OpenACCClauseEnqueue::VisitSelfClause(const OpenACCSelfClause &C) { if (C.hasConditionExpr()) Visitor.AddStmt(C.getConditionExpr()); } +void OpenACCClauseEnqueue::VisitNumWorkersClause( + const OpenACCNumWorkersClause &C) { + Visitor.AddStmt(C.getIntExpr()); +} +void OpenACCClauseEnqueue::VisitVectorLengthClause( + const OpenACCVectorLengthClause &C) { + Visitor.AddStmt(C.getIntExpr()); +} } // namespace void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index c24e442621c923c376ba2f2ed9d50f43f408b251..6945dff537cae141e596bed2aac3b4a55bbbb5d0 100644 --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -86,16 +86,13 @@ PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch, ExpectedPrinted, "input.cc"); } -::testing::AssertionResult PrintedDeclCXX11Matches( - StringRef Code, - const DeclarationMatcher &NodeMatch, - StringRef ExpectedPrinted) { +::testing::AssertionResult +PrintedDeclCXX11Matches(StringRef Code, const DeclarationMatcher &NodeMatch, + StringRef ExpectedPrinted, + PrintingPolicyAdjuster PolicyModifier = nullptr) { std::vector Args(1, "-std=c++11"); - return PrintedDeclMatches(Code, - Args, - NodeMatch, - ExpectedPrinted, - "input.cc"); + return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.cc", + PolicyModifier); } ::testing::AssertionResult PrintedDeclCXX11nonMSCMatches( @@ -1555,3 +1552,25 @@ TEST(DeclPrinter, VarDeclWithInitializer) { PrintedDeclCXX17Matches("void foo() {int arr[42]; for(int a : arr);}", namedDecl(hasName("a")).bind("id"), "int a")); } + +TEST(DeclPrinter, TestTemplateFinal) { + // By default we should print 'final' keyword whether class is implicitly or + // explicitly marked final. + ASSERT_TRUE(PrintedDeclCXX11Matches( + "template\n" + "class FinalTemplate final {};", + classTemplateDecl(hasName("FinalTemplate")).bind("id"), + "template class FinalTemplate final {}")); +} + +TEST(DeclPrinter, TestTemplateFinalWithPolishForDecl) { + // clangd relies on the 'final' keyword being printed when + // PolishForDeclaration is enabled, so make sure it is even if implicit attrs + // are disabled. + ASSERT_TRUE(PrintedDeclCXX11Matches( + "template\n" + "class FinalTemplate final {};", + classTemplateDecl(hasName("FinalTemplate")).bind("id"), + "template class FinalTemplate final {}", + [](PrintingPolicy &Policy) { Policy.PolishForDeclaration = true; })); +} diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp index cc20623f881ff450208b821353060e9c7229ec30..4195648161246c71551ad45601d1f96e49faa9af 100644 --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -150,56 +150,6 @@ TEST_F(EnvironmentTest, CreateValueRecursiveType) { EXPECT_THAT(PV, NotNull()); } -TEST_F(EnvironmentTest, JoinRecords) { - using namespace ast_matchers; - - std::string Code = R"cc( - struct S {}; - // Need to use the type somewhere so that the `QualType` gets created; - S s; - )cc"; - - auto Unit = - tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"}); - auto &Context = Unit->getASTContext(); - - ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U); - - auto Results = - match(qualType(hasDeclaration(recordDecl(hasName("S")))).bind("SType"), - Context); - const QualType *TyPtr = selectFirst("SType", Results); - ASSERT_THAT(TyPtr, NotNull()); - QualType Ty = *TyPtr; - ASSERT_FALSE(Ty.isNull()); - - auto *ConstructExpr = CXXConstructExpr::CreateEmpty(Context, 0); - ConstructExpr->setType(Ty); - ConstructExpr->setValueKind(VK_PRValue); - - // Two different `RecordValue`s with the same location are joined into a - // third `RecordValue` with that same location. - { - Environment Env1(DAContext); - auto &Val1 = *cast(Env1.createValue(Ty)); - RecordStorageLocation &Loc = Val1.getLoc(); - Env1.setValue(Loc, Val1); - - Environment Env2(DAContext); - auto &Val2 = Env2.create(Loc); - Env2.setValue(Loc, Val2); - Env2.setValue(Loc, Val2); - - Environment::ValueModel Model; - Environment EnvJoined = - Environment::join(Env1, Env2, Model, Environment::DiscardExprState); - auto *JoinedVal = cast(EnvJoined.getValue(Loc)); - EXPECT_NE(JoinedVal, &Val1); - EXPECT_NE(JoinedVal, &Val2); - EXPECT_EQ(&JoinedVal->getLoc(), &Loc); - } -} - TEST_F(EnvironmentTest, DifferentReferenceLocInJoin) { // This tests the case where the storage location for a reference-type // variable is different for two states being joined. We used to believe this @@ -453,35 +403,4 @@ TEST_F(EnvironmentTest, Contains(Member)); } -TEST_F(EnvironmentTest, RefreshRecordValue) { - using namespace ast_matchers; - - std::string Code = R"cc( - struct S {}; - void target () { - S s; - s; - } - )cc"; - - auto Unit = - tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"}); - auto &Context = Unit->getASTContext(); - - ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U); - - auto Results = match(functionDecl(hasName("target")).bind("target"), Context); - const auto *Target = selectFirst("target", Results); - ASSERT_THAT(Target, NotNull()); - - Results = match(declRefExpr(to(varDecl(hasName("s")))).bind("s"), Context); - const auto *DRE = selectFirst("s", Results); - ASSERT_THAT(DRE, NotNull()); - - Environment Env(DAContext, *Target); - EXPECT_THAT(Env.getStorageLocation(*DRE), IsNull()); - refreshRecordValue(*DRE, Env); - EXPECT_THAT(Env.getStorageLocation(*DRE), NotNull()); -} - } // namespace diff --git a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp index 55baa4e2a537757bbef087cf515553e8c4409af5..88b92668c850c6129b67ecd8020f5afd4eea7fba 100644 --- a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp @@ -85,10 +85,6 @@ TEST(RecordOpsTest, CopyRecord) { EXPECT_NE(Env.getValue(S1.getSyntheticField("synth_int")), Env.getValue(S2.getSyntheticField("synth_int"))); - auto *S1Val = cast(Env.getValue(S1)); - auto *S2Val = cast(Env.getValue(S2)); - EXPECT_NE(S1Val, S2Val); - copyRecord(S1, S2, Env); EXPECT_EQ(getFieldValue(&S1, *OuterIntDecl, Env), @@ -98,10 +94,6 @@ TEST(RecordOpsTest, CopyRecord) { getFieldValue(&Inner2, *InnerIntDecl, Env)); EXPECT_EQ(Env.getValue(S1.getSyntheticField("synth_int")), Env.getValue(S2.getSyntheticField("synth_int"))); - - S1Val = cast(Env.getValue(S1)); - S2Val = cast(Env.getValue(S2)); - EXPECT_NE(S1Val, S2Val); }); } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 97ec32126c1dc4c0d99cd147e85be54b39b3e795..bb16138126c8f973ad1b184b6b0b7ff617f9d5ff 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -260,9 +260,6 @@ TEST(TransferTest, StructIncomplete) { ASSERT_THAT(FooValue, NotNull()); EXPECT_TRUE(isa(FooValue->getPointeeLoc())); - auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc()); - ASSERT_THAT(FooPointeeValue, NotNull()); - EXPECT_TRUE(isa(FooPointeeValue)); }); } @@ -311,9 +308,10 @@ TEST(TransferTest, StructFieldUnmodeled) { const auto *FooLoc = cast(Env.getStorageLocation(*FooDecl)); - const auto *UnmodeledLoc = FooLoc->getChild(*UnmodeledDecl); - ASSERT_TRUE(isa(UnmodeledLoc)); - EXPECT_THAT(Env.getValue(*UnmodeledLoc), IsNull()); + const auto &UnmodeledLoc = + *cast(FooLoc->getChild(*UnmodeledDecl)); + StorageLocation &UnmodeledXLoc = getFieldLoc(UnmodeledLoc, "X", ASTCtx); + EXPECT_EQ(Env.getValue(UnmodeledXLoc), nullptr); const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab"); ASSERT_THAT(ZabDecl, NotNull()); @@ -492,9 +490,6 @@ TEST(TransferTest, ReferenceVarDecl) { const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); ASSERT_TRUE(isa_and_nonnull(FooLoc)); - - const Value *FooReferentVal = Env.getValue(*FooLoc); - EXPECT_TRUE(isa_and_nonnull(FooReferentVal)); }); } @@ -585,22 +580,21 @@ TEST(TransferTest, SelfReferentialReferenceVarDecl) { const auto &FooReferentLoc = *cast(BarLoc.getChild(*FooRefDecl)); - EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull()); - EXPECT_THAT(getFieldValue(&FooReferentLoc, *BarDecl, Env), IsNull()); + EXPECT_EQ(Env.getValue(*cast( + FooReferentLoc.getChild(*BarDecl)) + ->getChild(*FooPtrDecl)), + nullptr); const auto &FooPtrVal = *cast(getFieldValue(&BarLoc, *FooPtrDecl, Env)); const auto &FooPtrPointeeLoc = cast(FooPtrVal.getPointeeLoc()); - EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull()); - EXPECT_THAT(getFieldValue(&FooPtrPointeeLoc, *BarDecl, Env), IsNull()); - - EXPECT_THAT(getFieldValue(&BarLoc, *BazRefDecl, Env), NotNull()); + EXPECT_EQ(Env.getValue(*cast( + FooPtrPointeeLoc.getChild(*BarDecl)) + ->getChild(*FooPtrDecl)), + nullptr); - const auto &BazPtrVal = - *cast(getFieldValue(&BarLoc, *BazPtrDecl, Env)); - const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc(); - EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); + EXPECT_TRUE(isa(getFieldValue(&BarLoc, *BazPtrDecl, Env))); }); } @@ -631,9 +625,6 @@ TEST(TransferTest, PointerVarDecl) { const PointerValue *FooVal = cast(Env.getValue(*FooLoc)); const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); EXPECT_TRUE(isa(&FooPointeeLoc)); - - const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); - EXPECT_TRUE(isa_and_nonnull(FooPointeeVal)); }); } @@ -740,20 +731,14 @@ TEST(TransferTest, SelfReferentialPointerVarDecl) { const auto &BarPointeeLoc = cast(BarVal.getPointeeLoc()); - EXPECT_THAT(getFieldValue(&BarPointeeLoc, *FooRefDecl, Env), NotNull()); - const auto &FooPtrVal = *cast( getFieldValue(&BarPointeeLoc, *FooPtrDecl, Env)); const auto &FooPtrPointeeLoc = cast(FooPtrVal.getPointeeLoc()); - EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); - - EXPECT_THAT(getFieldValue(&BarPointeeLoc, *BazRefDecl, Env), NotNull()); + EXPECT_EQ(Env.getValue(*FooPtrPointeeLoc.getChild(*BarDecl)), nullptr); - const auto &BazPtrVal = *cast( - getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env)); - const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc(); - EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); + EXPECT_TRUE( + isa(getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env))); }); } @@ -1165,9 +1150,6 @@ TEST(TransferTest, ReferenceParamDecl) { const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); ASSERT_TRUE(isa_and_nonnull(FooLoc)); - - const Value *FooReferentVal = Env.getValue(*FooLoc); - EXPECT_TRUE(isa_and_nonnull(FooReferentVal)); }); } @@ -1196,9 +1178,6 @@ TEST(TransferTest, PointerParamDecl) { const PointerValue *FooVal = cast(Env.getValue(*FooLoc)); const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); EXPECT_TRUE(isa(&FooPointeeLoc)); - - const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); - EXPECT_TRUE(isa_and_nonnull(FooPointeeVal)); }); } @@ -1400,8 +1379,7 @@ static void derivedBaseMemberExpectations( const auto &FooLoc = *cast(Env.getStorageLocation(*FooDecl)); - const auto &FooVal = *cast(Env.getValue(FooLoc)); - EXPECT_EQ(&FooVal.getLoc(), &FooLoc); + EXPECT_NE(Env.getValue(*FooLoc.getChild(*BarDecl)), nullptr); } TEST(TransferTest, DerivedBaseMemberStructDefault) { @@ -1850,7 +1828,6 @@ TEST(TransferTest, StructThisMember) { const auto *QuxLoc = cast(ThisLoc->getChild(*QuxDecl)); - EXPECT_THAT(dyn_cast(Env.getValue(*QuxLoc)), NotNull()); const auto *BazVal = cast(getFieldValue(QuxLoc, *BazDecl, Env)); @@ -1921,7 +1898,6 @@ TEST(TransferTest, ClassThisMember) { const auto *QuxLoc = cast(ThisLoc->getChild(*QuxDecl)); - EXPECT_THAT(dyn_cast(Env.getValue(*QuxLoc)), NotNull()); const auto *BazVal = cast(getFieldValue(QuxLoc, *BazDecl, Env)); @@ -2297,10 +2273,6 @@ TEST(TransferTest, AssignmentOperator) { const auto *BarLoc2 = cast(Env2.getStorageLocation(*BarDecl)); - const auto *FooVal2 = cast(Env2.getValue(*FooLoc2)); - const auto *BarVal2 = cast(Env2.getValue(*BarLoc2)); - EXPECT_NE(FooVal2, BarVal2); - EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2)); const auto *FooBazVal2 = @@ -2652,12 +2624,7 @@ TEST(TransferTest, CopyConstructor) { const auto *BarLoc = cast(Env.getStorageLocation(*BarDecl)); - // `Foo` and `Bar` have different `RecordValue`s associated with them. - const auto *FooVal = cast(Env.getValue(*FooLoc)); - const auto *BarVal = cast(Env.getValue(*BarLoc)); - EXPECT_NE(FooVal, BarVal); - - // But the records compare equal. + // The records compare equal. EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); // In particular, the value of `Baz` in both records is the same. @@ -2878,10 +2845,6 @@ TEST(TransferTest, MoveConstructor) { EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1)); - const auto *FooVal1 = cast(Env1.getValue(*FooLoc1)); - const auto *BarVal1 = cast(Env1.getValue(*BarLoc1)); - EXPECT_NE(FooVal1, BarVal1); - const auto *FooBazVal1 = cast(getFieldValue(FooLoc1, *BazDecl, Env1)); const auto *BarBazVal1 = @@ -2890,8 +2853,6 @@ TEST(TransferTest, MoveConstructor) { const auto *FooLoc2 = cast(Env2.getStorageLocation(*FooDecl)); - const auto *FooVal2 = cast(Env2.getValue(*FooLoc2)); - EXPECT_NE(FooVal2, BarVal1); EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1)); const auto *FooBazVal2 = @@ -3098,6 +3059,79 @@ TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) { }); } +TEST(TransferTest, ResultObjectLocationForInitListExpr) { + std::string Code = R"cc( + struct Inner {}; + + struct Outer { Inner I; }; + + void target() { + Outer O = { Inner() }; + // [[p]] + } + )cc"; + using ast_matchers::asString; + using ast_matchers::cxxConstructExpr; + using ast_matchers::hasType; + using ast_matchers::match; + using ast_matchers::selectFirst; + using ast_matchers::traverse; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + auto *Construct = selectFirst( + "construct", + match( + cxxConstructExpr(hasType(asString("Inner"))).bind("construct"), + ASTCtx)); + + EXPECT_EQ( + &Env.getResultObjectLocation(*Construct), + &getFieldLoc(getLocForDecl(ASTCtx, Env, "O"), + "I", ASTCtx)); + }); +} + +TEST(TransferTest, ResultObjectLocationForParenInitListExpr) { + std::string Code = R"cc( + struct Inner {}; + + struct Outer { Inner I; }; + + void target() { + Outer O((Inner())); + // [[p]] + } + )cc"; + using ast_matchers::asString; + using ast_matchers::cxxConstructExpr; + using ast_matchers::hasType; + using ast_matchers::match; + using ast_matchers::selectFirst; + using ast_matchers::traverse; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + auto *Construct = selectFirst( + "construct", + match( + cxxConstructExpr(hasType(asString("Inner"))).bind("construct"), + ASTCtx)); + + EXPECT_EQ( + &Env.getResultObjectLocation(*Construct), + &getFieldLoc(getLocForDecl(ASTCtx, Env, "O"), + "I", ASTCtx)); + }, + LangStandard::lang_cxx20); +} + // Check that the `std::strong_ordering` object returned by builtin `<=>` has a // correctly modeled result object location. TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) { @@ -3443,7 +3477,8 @@ TEST(TransferTest, NullToPointerCast) { const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); EXPECT_TRUE(isa(BazPointeeLoc)); - EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); + EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue( + BazPointeeLoc.getType())); const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc(); EXPECT_TRUE(isa(NullPointeeLoc)); @@ -3597,10 +3632,14 @@ TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) { TEST(TransferTest, VarDeclInitAssignConditionalOperator) { std::string Code = R"( - struct A {}; + struct A { + int i; + }; void target(A Foo, A Bar, bool Cond) { A Baz = Cond ? Foo : Bar; + // Make sure A::i is modeled. + Baz.i; /*[[p]]*/ } )"; @@ -3608,26 +3647,20 @@ TEST(TransferTest, VarDeclInitAssignConditionalOperator) { Code, [](const llvm::StringMap> &Results, ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); - ASSERT_THAT(FooDecl, NotNull()); + auto *FooIVal = cast(getFieldValue( + &getLocForDecl(ASTCtx, Env, "Foo"), "i", + ASTCtx, Env)); + auto *BarIVal = cast(getFieldValue( + &getLocForDecl(ASTCtx, Env, "Bar"), "i", + ASTCtx, Env)); + auto *BazIVal = cast(getFieldValue( + &getLocForDecl(ASTCtx, Env, "Baz"), "i", + ASTCtx, Env)); - const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); - ASSERT_THAT(BarDecl, NotNull()); - - const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); - ASSERT_THAT(BazDecl, NotNull()); - - const auto *FooVal = cast(Env.getValue(*FooDecl)); - const auto *BarVal = cast(Env.getValue(*BarDecl)); - - const auto *BazVal = dyn_cast(Env.getValue(*BazDecl)); - ASSERT_THAT(BazVal, NotNull()); - - EXPECT_NE(BazVal, FooVal); - EXPECT_NE(BazVal, BarVal); + EXPECT_NE(BazIVal, FooIVal); + EXPECT_NE(BazIVal, BarIVal); }); } @@ -3894,7 +3927,6 @@ TEST(TransferTest, AssignToUnionMember) { const auto *BazLoc = dyn_cast_or_null( Env.getStorageLocation(*BazDecl)); ASSERT_THAT(BazLoc, NotNull()); - ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); const auto *FooVal = cast(getFieldValue(BazLoc, *FooDecl, Env)); @@ -5485,17 +5517,15 @@ TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { ASSERT_THAT(SDecl, NotNull()); auto *SLoc = Env.getStorageLocation(*SDecl); - ASSERT_THAT(SLoc, NotNull()); - EXPECT_THAT(Env.getValue(*SLoc), NotNull()); + EXPECT_THAT(SLoc, NotNull()); auto *Loc = Env.getReturnStorageLocation(); - ASSERT_THAT(Loc, NotNull()); - EXPECT_THAT(Env.getValue(*Loc), NotNull()); + 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. - // ASSERT_THAT(Loc, Eq(SLoc)); + // EXPECT_EQ(Loc, SLoc); }, {BuiltinOptions{ContextSensitiveOptions{}}}); } @@ -6561,7 +6591,7 @@ TEST(TransferTest, NewExpressions_Structs) { void target() { Outer *p = new Outer; // Access the fields to make sure the analysis actually generates children - // for them in the `RecordStorageLocation` and `RecordValue`. + // for them in the `RecordStorageLocation`. p->OuterField.InnerField; // [[after_new]] } @@ -6583,9 +6613,6 @@ TEST(TransferTest, NewExpressions_Structs) { *cast(OuterLoc.getChild(*OuterField)); auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField); - // Values for the struct and all fields exist after the new. - EXPECT_THAT(Env.getValue(OuterLoc), NotNull()); - EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull()); EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull()); }); } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 4906b3350b5b229798b7103126beaf08664e7d8d..bc61b9c089e9223dbf6d8dd81eb44b9b31cf3ae7 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -27339,12 +27339,6 @@ TEST_F(FormatTest, PPDirectivesAndCommentsInBracedInit) { getLLVMStyleWithColumns(30)); } -TEST_F(FormatTest, StreamOutputOperator) { - verifyFormat("std::cout << \"foo\" << \"bar\" << baz;"); - verifyFormat("std::cout << \"foo\\n\"\n" - " << \"bar\";"); -} - TEST_F(FormatTest, BreakAdjacentStringLiterals) { constexpr StringRef Code{ "return \"Code\" \"\\0\\52\\26\\55\\55\\0\" \"x013\" \"\\02\\xBA\";"}; @@ -27359,6 +27353,7 @@ TEST_F(FormatTest, BreakAdjacentStringLiterals) { Style.BreakAdjacentStringLiterals = false; verifyFormat(Code, Style); } + } // namespace } // namespace test } // namespace format diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index da02ced8c7a9499005a9ff90fa0304da30a41572..4f445c64ab303a2d050630307d58f9e86025d95c 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -309,6 +309,16 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_OverloadedOperatorLParen); EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_FunctionLBrace); EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference); + + Tokens = annotate("if (new && num) {\n" + " new = 1;\n" + "}\n" + "if (!delete && num) {\n" + " delete = 1;\n" + "}"); + ASSERT_EQ(Tokens.size(), 26u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_BinaryOperator); + EXPECT_TOKEN(Tokens[16], tok::ampamp, TT_BinaryOperator); } TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) { @@ -2841,15 +2851,6 @@ TEST_F(TokenAnnotatorTest, BraceKind) { EXPECT_BRACE_KIND(Tokens[16], BK_BracedInit); } -TEST_F(TokenAnnotatorTest, StreamOperator) { - auto Tokens = annotate("\"foo\\n\" << aux << \"foo\\n\" << \"foo\";"); - ASSERT_EQ(Tokens.size(), 9u) << Tokens; - EXPECT_FALSE(Tokens[1]->MustBreakBefore); - EXPECT_FALSE(Tokens[3]->MustBreakBefore); - // Only break between string literals if the former ends with \n. - EXPECT_TRUE(Tokens[5]->MustBreakBefore); -} - TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) { auto Tokens = annotate("auto foo() -> enum En {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 6c56f99f503df48fb7914dc9ff04252e162431c6..765cbbf3b04bcfad900404aa0246ba0d2e37a6c8 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1608,7 +1608,7 @@ writePrettyPrintFunction(const Record &R, Prefix = "["; Suffix = "]"; } else if (Variety == "Keyword") { - Prefix = " "; + Prefix = ""; Suffix = ""; } else if (Variety == "Pragma") { Prefix = "#pragma "; diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 9893170ae847396585076689647602a61cffa981..dfc1afefda245f7a844c9bc9258f6b98801ae34d 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -295,11 +295,6 @@ conformance.

N570 Yes - - new structure type compatibility (tag compatibility) - N522 - Unknown - additional predefined macro names Unknown diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index 6d413f6753bc0cc802b2b91671fa4c483310ef5f..a6c6ef93500d53b8fb90508d5e1a727863deba4d 100644 --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -369,7 +369,7 @@ macro(construct_compiler_rt_default_triple) endif() if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") - execute_process(COMMAND ${CMAKE_C_COMPILER} --target=${COMPILER_RT_DEFAULT_TARGET_TRIPLE} -print-effective-triple + execute_process(COMMAND ${CMAKE_C_COMPILER} --target=${COMPILER_RT_DEFAULT_TARGET_TRIPLE} -print-target-triple OUTPUT_VARIABLE COMPILER_RT_DEFAULT_TARGET_TRIPLE OUTPUT_STRIP_TRAILING_WHITESPACE) endif() diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index f2b4ac72ae157384305a5cb36937505760263d3d..66f2d259aa5fd46bc627f91789435a846f65414f 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -122,9 +122,6 @@ set(SANITIZER_IMPL_HEADERS sanitizer_asm.h sanitizer_atomic.h sanitizer_atomic_clang.h - sanitizer_atomic_clang_mips.h - sanitizer_atomic_clang_other.h - sanitizer_atomic_clang_x86.h sanitizer_atomic_msvc.h sanitizer_bitvector.h sanitizer_bvgraph.h diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h index 46f06957228c9b81c7aa3acbe7fa9bb16bcd3df6..0609a11ffdebb0a317f83921f5318b9132187229 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_atomic.h @@ -18,12 +18,24 @@ namespace __sanitizer { enum memory_order { +// If the __atomic atomic builtins are supported (Clang/GCC), use the +// compiler provided macro values so that we can map the atomic operations +// to __atomic_* directly. +#ifdef __ATOMIC_SEQ_CST + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +#else memory_order_relaxed = 1 << 0, memory_order_consume = 1 << 1, memory_order_acquire = 1 << 2, memory_order_release = 1 << 3, memory_order_acq_rel = 1 << 4, memory_order_seq_cst = 1 << 5 +#endif }; struct atomic_uint8_t { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h index 4318d64d16cfa21114dc50de6a45b3b15318d8b6..1414092e38d7e2cc7d3ea2ed8aa47eeecfcba1a1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h @@ -14,60 +14,63 @@ #ifndef SANITIZER_ATOMIC_CLANG_H #define SANITIZER_ATOMIC_CLANG_H -#if defined(__i386__) || defined(__x86_64__) -# include "sanitizer_atomic_clang_x86.h" -#else -# include "sanitizer_atomic_clang_other.h" -#endif - namespace __sanitizer { -// We would like to just use compiler builtin atomic operations -// for loads and stores, but they are mostly broken in clang: -// - they lead to vastly inefficient code generation -// (http://llvm.org/bugs/show_bug.cgi?id=17281) -// - 64-bit atomic operations are not implemented on x86_32 -// (http://llvm.org/bugs/show_bug.cgi?id=15034) -// - they are not implemented on ARM -// error: undefined reference to '__atomic_load_4' +// We use the compiler builtin atomic operations for loads and stores, which +// generates correct code for all architectures, but may require libatomic +// on platforms where e.g. 64-bit atomics are not supported natively. // See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html // for mappings of the memory model to different processors. -inline void atomic_signal_fence(memory_order) { +inline void atomic_signal_fence(memory_order mo) { __atomic_signal_fence(mo); } + +inline void atomic_thread_fence(memory_order mo) { __atomic_thread_fence(mo); } + +inline void proc_yield(int cnt) { + __asm__ __volatile__("" ::: "memory"); +#if defined(__i386__) || defined(__x86_64__) + for (int i = 0; i < cnt; i++) __asm__ __volatile__("pause"); __asm__ __volatile__("" ::: "memory"); +#endif } -inline void atomic_thread_fence(memory_order) { - __sync_synchronize(); +template +inline typename T::Type atomic_load(const volatile T *a, memory_order mo) { + DCHECK(mo == memory_order_relaxed || mo == memory_order_consume || + mo == memory_order_acquire || mo == memory_order_seq_cst); + DCHECK(!((uptr)a % sizeof(*a))); + return __atomic_load_n(&a->val_dont_use, mo); } -template -inline typename T::Type atomic_fetch_add(volatile T *a, - typename T::Type v, memory_order mo) { - (void)mo; +template +inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { + DCHECK(mo == memory_order_relaxed || mo == memory_order_release || + mo == memory_order_seq_cst); DCHECK(!((uptr)a % sizeof(*a))); - return __sync_fetch_and_add(&a->val_dont_use, v); + __atomic_store_n(&a->val_dont_use, v, mo); } -template -inline typename T::Type atomic_fetch_sub(volatile T *a, - typename T::Type v, memory_order mo) { +template +inline typename T::Type atomic_fetch_add(volatile T *a, typename T::Type v, + memory_order mo) { + DCHECK(!((uptr)a % sizeof(*a))); + return __atomic_fetch_add(&a->val_dont_use, v, mo); +} + +template +inline typename T::Type atomic_fetch_sub(volatile T *a, typename T::Type v, + memory_order mo) { (void)mo; DCHECK(!((uptr)a % sizeof(*a))); - return __sync_fetch_and_add(&a->val_dont_use, -v); + return __atomic_fetch_sub(&a->val_dont_use, v, mo); } -template -inline typename T::Type atomic_exchange(volatile T *a, - typename T::Type v, memory_order mo) { +template +inline typename T::Type atomic_exchange(volatile T *a, typename T::Type v, + memory_order mo) { DCHECK(!((uptr)a % sizeof(*a))); - if (mo & (memory_order_release | memory_order_acq_rel | memory_order_seq_cst)) - __sync_synchronize(); - v = __sync_lock_test_and_set(&a->val_dont_use, v); - if (mo == memory_order_seq_cst) - __sync_synchronize(); - return v; + return __atomic_exchange_n(&a->val_dont_use, v, mo); } template @@ -82,9 +85,8 @@ inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } -template -inline bool atomic_compare_exchange_weak(volatile T *a, - typename T::Type *cmp, +template +inline bool atomic_compare_exchange_weak(volatile T *a, typename T::Type *cmp, typename T::Type xchg, memory_order mo) { return atomic_compare_exchange_strong(a, cmp, xchg, mo); @@ -92,13 +94,6 @@ inline bool atomic_compare_exchange_weak(volatile T *a, } // namespace __sanitizer -// This include provides explicit template instantiations for atomic_uint64_t -// on MIPS32, which does not directly support 8 byte atomics. It has to -// proceed the template definitions above. -#if defined(_MIPS_SIM) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 -# include "sanitizer_atomic_clang_mips.h" -#endif - #undef ATOMIC_ORDER #endif // SANITIZER_ATOMIC_CLANG_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h deleted file mode 100644 index f3d3052e5b7c5c22b5171d3c14c5d325618ab1a4..0000000000000000000000000000000000000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h +++ /dev/null @@ -1,117 +0,0 @@ -//===-- sanitizer_atomic_clang_mips.h ---------------------------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Not intended for direct inclusion. Include sanitizer_atomic.h. -// -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_ATOMIC_CLANG_MIPS_H -#define SANITIZER_ATOMIC_CLANG_MIPS_H - -namespace __sanitizer { - -// MIPS32 does not support atomics > 4 bytes. To address this lack of -// functionality, the sanitizer library provides helper methods which use an -// internal spin lock mechanism to emulate atomic operations when the size is -// 8 bytes. -static void __spin_lock(volatile int *lock) { - while (__sync_lock_test_and_set(lock, 1)) - while (*lock) { - } -} - -static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); } - -// Make sure the lock is on its own cache line to prevent false sharing. -// Put it inside a struct that is aligned and padded to the typical MIPS -// cacheline which is 32 bytes. -static struct { - int lock; - char pad[32 - sizeof(int)]; -} __attribute__((aligned(32))) lock = {0, {0}}; - -template <> -inline atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr, - atomic_uint64_t::Type val, - memory_order mo) { - DCHECK(mo & - (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); - DCHECK(!((uptr)ptr % sizeof(*ptr))); - - atomic_uint64_t::Type ret; - - __spin_lock(&lock.lock); - ret = *(const_cast(&ptr->val_dont_use)); - ptr->val_dont_use = ret + val; - __spin_unlock(&lock.lock); - - return ret; -} - -template <> -inline atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr, - atomic_uint64_t::Type val, - memory_order mo) { - return atomic_fetch_add(ptr, -val, mo); -} - -template <> -inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr, - atomic_uint64_t::Type *cmp, - atomic_uint64_t::Type xchg, - memory_order mo) { - DCHECK(mo & - (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); - DCHECK(!((uptr)ptr % sizeof(*ptr))); - - typedef atomic_uint64_t::Type Type; - Type cmpv = *cmp; - Type prev; - bool ret = false; - - __spin_lock(&lock.lock); - prev = *(const_cast(&ptr->val_dont_use)); - if (prev == cmpv) { - ret = true; - ptr->val_dont_use = xchg; - } - __spin_unlock(&lock.lock); - - return ret; -} - -template <> -inline atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr, - memory_order mo) { - DCHECK(mo & - (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); - DCHECK(!((uptr)ptr % sizeof(*ptr))); - - atomic_uint64_t::Type zero = 0; - volatile atomic_uint64_t *Newptr = - const_cast(ptr); - return atomic_fetch_add(Newptr, zero, mo); -} - -template <> -inline void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v, - memory_order mo) { - DCHECK(mo & - (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); - DCHECK(!((uptr)ptr % sizeof(*ptr))); - - __spin_lock(&lock.lock); - ptr->val_dont_use = v; - __spin_unlock(&lock.lock); -} - -} // namespace __sanitizer - -#endif // SANITIZER_ATOMIC_CLANG_MIPS_H - diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h deleted file mode 100644 index 557082a636b8798b4757bb97c67e953773ef78e5..0000000000000000000000000000000000000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h +++ /dev/null @@ -1,85 +0,0 @@ -//===-- sanitizer_atomic_clang_other.h --------------------------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Not intended for direct inclusion. Include sanitizer_atomic.h. -// -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_ATOMIC_CLANG_OTHER_H -#define SANITIZER_ATOMIC_CLANG_OTHER_H - -namespace __sanitizer { - - -inline void proc_yield(int cnt) { - __asm__ __volatile__("" ::: "memory"); -} - -template -inline typename T::Type atomic_load( - const volatile T *a, memory_order mo) { - DCHECK(mo & (memory_order_relaxed | memory_order_consume - | memory_order_acquire | memory_order_seq_cst)); - DCHECK(!((uptr)a % sizeof(*a))); - typename T::Type v; - - if (sizeof(*a) < 8 || sizeof(void*) == 8) { - // Assume that aligned loads are atomic. - if (mo == memory_order_relaxed) { - v = a->val_dont_use; - } else if (mo == memory_order_consume) { - // Assume that processor respects data dependencies - // (and that compiler won't break them). - __asm__ __volatile__("" ::: "memory"); - v = a->val_dont_use; - __asm__ __volatile__("" ::: "memory"); - } else if (mo == memory_order_acquire) { - __asm__ __volatile__("" ::: "memory"); - v = a->val_dont_use; - __sync_synchronize(); - } else { // seq_cst - // E.g. on POWER we need a hw fence even before the store. - __sync_synchronize(); - v = a->val_dont_use; - __sync_synchronize(); - } - } else { - __atomic_load(const_cast(&a->val_dont_use), &v, - __ATOMIC_SEQ_CST); - } - return v; -} - -template -inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { - DCHECK(mo & (memory_order_relaxed | memory_order_release - | memory_order_seq_cst)); - DCHECK(!((uptr)a % sizeof(*a))); - - if (sizeof(*a) < 8 || sizeof(void*) == 8) { - // Assume that aligned stores are atomic. - if (mo == memory_order_relaxed) { - a->val_dont_use = v; - } else if (mo == memory_order_release) { - __sync_synchronize(); - a->val_dont_use = v; - __asm__ __volatile__("" ::: "memory"); - } else { // seq_cst - __sync_synchronize(); - a->val_dont_use = v; - __sync_synchronize(); - } - } else { - __atomic_store(&a->val_dont_use, &v, __ATOMIC_SEQ_CST); - } -} - -} // namespace __sanitizer - -#endif // #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h deleted file mode 100644 index b81a354d20987299110c0f46cb2b777d3a12679e..0000000000000000000000000000000000000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h +++ /dev/null @@ -1,113 +0,0 @@ -//===-- sanitizer_atomic_clang_x86.h ----------------------------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Not intended for direct inclusion. Include sanitizer_atomic.h. -// -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_ATOMIC_CLANG_X86_H -#define SANITIZER_ATOMIC_CLANG_X86_H - -namespace __sanitizer { - -inline void proc_yield(int cnt) { - __asm__ __volatile__("" ::: "memory"); - for (int i = 0; i < cnt; i++) - __asm__ __volatile__("pause"); - __asm__ __volatile__("" ::: "memory"); -} - -template -inline typename T::Type atomic_load( - const volatile T *a, memory_order mo) { - DCHECK(mo & (memory_order_relaxed | memory_order_consume - | memory_order_acquire | memory_order_seq_cst)); - DCHECK(!((uptr)a % sizeof(*a))); - typename T::Type v; - - if (sizeof(*a) < 8 || sizeof(void*) == 8) { - // Assume that aligned loads are atomic. - if (mo == memory_order_relaxed) { - v = a->val_dont_use; - } else if (mo == memory_order_consume) { - // Assume that processor respects data dependencies - // (and that compiler won't break them). - __asm__ __volatile__("" ::: "memory"); - v = a->val_dont_use; - __asm__ __volatile__("" ::: "memory"); - } else if (mo == memory_order_acquire) { - __asm__ __volatile__("" ::: "memory"); - v = a->val_dont_use; - // On x86 loads are implicitly acquire. - __asm__ __volatile__("" ::: "memory"); - } else { // seq_cst - // On x86 plain MOV is enough for seq_cst store. - __asm__ __volatile__("" ::: "memory"); - v = a->val_dont_use; - __asm__ __volatile__("" ::: "memory"); - } - } else { - // 64-bit load on 32-bit platform. - __asm__ __volatile__( - "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves - "movq %%mm0, %0;" // (ptr could be read-only) - "emms;" // Empty mmx state/Reset FP regs - : "=m" (v) - : "m" (a->val_dont_use) - : // mark the mmx registers as clobbered -#ifdef __MMX__ - "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", -#endif // #ifdef __MMX__ - "memory"); - } - return v; -} - -template -inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { - DCHECK(mo & (memory_order_relaxed | memory_order_release - | memory_order_seq_cst)); - DCHECK(!((uptr)a % sizeof(*a))); - - if (sizeof(*a) < 8 || sizeof(void*) == 8) { - // Assume that aligned stores are atomic. - if (mo == memory_order_relaxed) { - a->val_dont_use = v; - } else if (mo == memory_order_release) { - // On x86 stores are implicitly release. - __asm__ __volatile__("" ::: "memory"); - a->val_dont_use = v; - __asm__ __volatile__("" ::: "memory"); - } else { // seq_cst - // On x86 stores are implicitly release. - __asm__ __volatile__("" ::: "memory"); - a->val_dont_use = v; - __sync_synchronize(); - } - } else { - // 64-bit store on 32-bit platform. - __asm__ __volatile__( - "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves - "movq %%mm0, %0;" - "emms;" // Empty mmx state/Reset FP regs - : "=m" (a->val_dont_use) - : "m" (v) - : // mark the mmx registers as clobbered -#ifdef __MMX__ - "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", -#endif // #ifdef __MMX__ - "memory"); - if (mo == memory_order_seq_cst) - __sync_synchronize(); - } -} - -} // namespace __sanitizer - -#endif // #ifndef SANITIZER_ATOMIC_CLANG_X86_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h index 31317adcdfc99fd59708b4ac4db60deee4c65e9b..d80bfdbf6a0812a91c851dc0004532fa82fdaf34 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h @@ -70,8 +70,8 @@ inline void proc_yield(int cnt) { template inline typename T::Type atomic_load( const volatile T *a, memory_order mo) { - DCHECK(mo & (memory_order_relaxed | memory_order_consume - | memory_order_acquire | memory_order_seq_cst)); + DCHECK(mo == memory_order_relaxed || mo == memory_order_consume || + mo == memory_order_acquire || mo == memory_order_seq_cst); DCHECK(!((uptr)a % sizeof(*a))); typename T::Type v; // FIXME(dvyukov): 64-bit load is not atomic on 32-bits. @@ -87,8 +87,8 @@ inline typename T::Type atomic_load( template inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { - DCHECK(mo & (memory_order_relaxed | memory_order_release - | memory_order_seq_cst)); + DCHECK(mo == memory_order_relaxed || mo == memory_order_release || + mo == memory_order_seq_cst); DCHECK(!((uptr)a % sizeof(*a))); // FIXME(dvyukov): 64-bit store is not atomic on 32-bits. if (mo == memory_order_relaxed) { diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index c8e75024823f2cc98f4dacc0bc9125f588e216fe..71141e5efac4888cb03b32f2aa0bcc891f892f66 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -81,13 +81,12 @@ 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 BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) + get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} REALPATH) 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 @@ -98,7 +97,7 @@ if (FLANG_STANDALONE_BUILD) CLANG_DIR_ABSOLUTE ${CLANG_DIR} REALPATH - BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) + ${CMAKE_CURRENT_SOURCE_DIR}) list(APPEND CMAKE_MODULE_PATH ${CLANG_DIR_ABSOLUTE}) # TODO: Remove when libclangDriver is lifted out of Clang @@ -125,14 +124,13 @@ 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 BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) + get_filename_component(MLIR_DIR_ABSOLUTE ${MLIR_DIR} REALPATH) 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/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index 580e840587abb298f3feaccffc98fac619a6a6ad..92790a691e473170785131260f1c5098a3ca9d07 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -3200,7 +3200,7 @@ def fir_CUDAAllocateOp : fir_Op<"cuda_allocate", [AttrSizedOperandSegments, is initialized before with the standard flang runtime calls. }]; - let arguments = (ins Arg:$box, + let arguments = (ins Arg:$box, Arg, "", [MemWrite]>:$errmsg, Optional:$stream, Arg, "", [MemWrite]>:$pinned, diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index 187796d77cf5c12f793fcc3e69b5cd5a8e986297..bfc0db8124af21cd42e42c5b6539c2892fecc5b8 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -204,7 +204,7 @@ def MemRefDataFlowOpt : Pass<"fir-memref-dataflow-opt", "::mlir::func::FuncOp"> def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> { let summary = "Add the debug info"; let description = [{ - Add the foundation for emitting debug info that can be understood by llvm. + Emit debug info that can be understood by llvm. }]; let constructor = "::fir::createAddDebugInfoPass()"; let dependentDialects = [ diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 268d00b5a60535e9fc83f2d12ee169a2232097b1..ea297fb337a2c84f86680d79510806f2eff60ea3 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -76,7 +76,7 @@ static llvm::cl::opt useOldAliasTags("use-old-alias-tags", #if !defined(FLANG_EXCLUDE_CODEGEN) DisableOption(CodeGenRewrite, "codegen-rewrite", "rewrite FIR for codegen"); DisableOption(TargetRewrite, "target-rewrite", "rewrite FIR for target"); -DisableOption(DebugFoundation, "debug-foundation", "Add debug foundation"); +DisableOption(DebugInfo, "debug-info", "Add debug info"); DisableOption(FirToLlvmIr, "fir-to-llvmir", "FIR to LLVM-IR dialect"); DisableOption(LlvmIrToLlvm, "llvm", "conversion to LLVM"); DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite", @@ -156,8 +156,8 @@ inline void addTargetRewritePass(mlir::PassManager &pm) { } inline void addDebugInfoPass(mlir::PassManager &pm) { - addPassConditionally(pm, disableDebugFoundation, - [&]() { return fir::createAddDebugInfoPass(); }); + addPassConditionally( + pm, disableDebugInfo, [&]() { return fir::createAddDebugInfoPass(); }); } inline void addFIRToLLVMPass( diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 42e78fc96e4445a6c1bf5b7f445198f2562b8b08..38f61528d7e28add5a500e16dcdd25a954e5fd61 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -14,6 +14,7 @@ #include "flang/Evaluate/tools.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/ConvertType.h" +#include "flang/Lower/ConvertVariable.h" #include "flang/Lower/IterationSpace.h" #include "flang/Lower/Mangler.h" #include "flang/Lower/OpenACC.h" @@ -368,20 +369,17 @@ private: [&](const Fortran::parser::AllocOpt::Mold &mold) { moldExpr = Fortran::semantics::GetExpr(mold.v.value()); }, - [&](const Fortran::parser::AllocOpt::Stream &) { - TODO(loc, "CUDA ALLOCATE(STREAM=)"); + [&](const Fortran::parser::AllocOpt::Stream &stream) { + streamExpr = Fortran::semantics::GetExpr(stream.v.value()); }, - [&](const Fortran::parser::AllocOpt::Pinned &) { - TODO(loc, "CUDA ALLOCATE(PINNED=)"); + [&](const Fortran::parser::AllocOpt::Pinned &pinned) { + pinnedExpr = Fortran::semantics::GetExpr(pinned.v.value()); }, }, allocOption.u); } void lowerAllocation(const Allocation &alloc) { - if (Fortran::semantics::HasCUDAAttr(alloc.getSymbol())) - TODO(loc, "Allocation of variable with CUDA attributes"); - fir::MutableBoxValue boxAddr = genMutableBoxValue(converter, loc, alloc.getAllocObj()); @@ -456,7 +454,8 @@ private: const fir::MutableBoxValue &box) { if (!box.isDerived() && !errorManager.hasStatSpec() && !alloc.type.IsPolymorphic() && !alloc.hasCoarraySpec() && - !useAllocateRuntime && !box.isPointer()) { + !useAllocateRuntime && !box.isPointer() && + !Fortran::semantics::HasCUDAAttr(alloc.getSymbol())) { // Pointers must use PointerAllocate so that their deallocations // can be validated. genInlinedAllocation(alloc, box); @@ -472,7 +471,12 @@ private: genSetType(alloc, box, loc); genSetDeferredLengthParameters(alloc, box); genAllocateObjectBounds(alloc, box); - mlir::Value stat = genRuntimeAllocate(builder, loc, box, errorManager); + mlir::Value stat; + if (!Fortran::semantics::HasCUDAAttr(alloc.getSymbol())) + stat = genRuntimeAllocate(builder, loc, box, errorManager); + else + stat = + genCudaAllocate(builder, loc, box, errorManager, alloc.getSymbol()); fir::factory::syncMutableBoxFromIRBox(builder, loc, box); postAllocationAction(alloc); errorManager.assignStat(builder, loc, stat); @@ -602,7 +606,10 @@ private: genSetDeferredLengthParameters(alloc, box); genAllocateObjectBounds(alloc, box); mlir::Value stat; - if (isSource) + if (Fortran::semantics::HasCUDAAttr(alloc.getSymbol())) + stat = + genCudaAllocate(builder, loc, box, errorManager, alloc.getSymbol()); + else if (isSource) stat = genRuntimeAllocateSource(builder, loc, box, exv, errorManager); else stat = genRuntimeAllocate(builder, loc, box, errorManager); @@ -717,6 +724,34 @@ private: return nullptr; } + mlir::Value genCudaAllocate(fir::FirOpBuilder &builder, mlir::Location loc, + const fir::MutableBoxValue &box, + ErrorManager &errorManager, + const Fortran::semantics::Symbol &sym) { + Fortran::lower::StatementContext stmtCtx; + fir::CUDADataAttributeAttr cudaAttr = + Fortran::lower::translateSymbolCUDADataAttribute(builder.getContext(), + sym); + mlir::Value errmsg = errMsgExpr ? errorManager.errMsgAddr : nullptr; + mlir::Value stream = + streamExpr + ? fir::getBase(converter.genExprValue(loc, *streamExpr, stmtCtx)) + : nullptr; + mlir::Value pinned = + pinnedExpr + ? fir::getBase(converter.genExprAddr(loc, *pinnedExpr, stmtCtx)) + : nullptr; + mlir::Value source = sourceExpr ? fir::getBase(sourceExv) : nullptr; + + // Keep return type the same as a standard AllocatableAllocate call. + mlir::Type retTy = fir::runtime::getModel()(builder.getContext()); + return builder + .create( + loc, retTy, box.getAddr(), errmsg, stream, pinned, source, cudaAttr, + errorManager.hasStatSpec() ? builder.getUnitAttr() : nullptr) + .getResult(); + } + Fortran::lower::AbstractConverter &converter; fir::FirOpBuilder &builder; const Fortran::parser::AllocateStmt &stmt; @@ -724,6 +759,8 @@ private: const Fortran::lower::SomeExpr *moldExpr{nullptr}; const Fortran::lower::SomeExpr *statExpr{nullptr}; const Fortran::lower::SomeExpr *errMsgExpr{nullptr}; + const Fortran::lower::SomeExpr *pinnedExpr{nullptr}; + const Fortran::lower::SomeExpr *streamExpr{nullptr}; // If the allocate has a type spec, lenParams contains the // value of the length parameters that were specified inside. llvm::SmallVector lenParams; @@ -762,6 +799,28 @@ static void postDeallocationAction(Fortran::lower::AbstractConverter &converter, Fortran::lower::attachDeclarePostDeallocAction(converter, builder, sym); } +static mlir::Value genCudaDeallocate(fir::FirOpBuilder &builder, + mlir::Location loc, + const fir::MutableBoxValue &box, + ErrorManager &errorManager, + const Fortran::semantics::Symbol &sym) { + fir::CUDADataAttributeAttr cudaAttr = + Fortran::lower::translateSymbolCUDADataAttribute(builder.getContext(), + sym); + mlir::Value errmsg = + mlir::isa(errorManager.errMsgAddr.getDefiningOp()) + ? nullptr + : errorManager.errMsgAddr; + + // Keep return type the same as a standard AllocatableAllocate call. + mlir::Type retTy = fir::runtime::getModel()(builder.getContext()); + return builder + .create( + loc, retTy, box.getAddr(), errmsg, cudaAttr, + errorManager.hasStatSpec() ? builder.getUnitAttr() : nullptr) + .getResult(); +} + // Generate deallocation of a pointer/allocatable. static mlir::Value genDeallocate(fir::FirOpBuilder &builder, @@ -769,10 +828,11 @@ genDeallocate(fir::FirOpBuilder &builder, const fir::MutableBoxValue &box, ErrorManager &errorManager, mlir::Value declaredTypeDesc = {}, const Fortran::semantics::Symbol *symbol = nullptr) { + bool isCudaSymbol = symbol && Fortran::semantics::HasCUDAAttr(*symbol); // Deallocate intrinsic types inline. if (!box.isDerived() && !box.isPolymorphic() && !box.isUnlimitedPolymorphic() && !errorManager.hasStatSpec() && - !useAllocateRuntime && !box.isPointer()) { + !useAllocateRuntime && !box.isPointer() && !isCudaSymbol) { // Pointers must use PointerDeallocate so that their deallocations // can be validated. mlir::Value ret = fir::factory::genFreemem(builder, loc, box); @@ -783,8 +843,12 @@ genDeallocate(fir::FirOpBuilder &builder, // Use runtime calls to deallocate descriptor cases. Sync MutableBoxValue // with its descriptor before and after calls if needed. errorManager.genStatCheck(builder, loc); - mlir::Value stat = - genRuntimeDeallocate(builder, loc, box, errorManager, declaredTypeDesc); + mlir::Value stat; + if (!isCudaSymbol) + stat = + genRuntimeDeallocate(builder, loc, box, errorManager, declaredTypeDesc); + else + stat = genCudaDeallocate(builder, loc, box, errorManager, *symbol); fir::factory::syncMutableBoxFromIRBox(builder, loc, box); if (symbol) postDeallocationAction(converter, builder, *symbol); diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index be27256d911b31bd6e1c823630c90ff5e9b54b81..5c24c95db427aa9e2a325a0112547da53f42f0a6 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -3998,7 +3998,7 @@ mlir::LogicalResult fir::CUDAAllocateOp::verify() { return emitOpError("pinned and stream cannot appears at the same time"); if (!fir::unwrapRefType(getBox().getType()).isa()) return emitOpError( - "expect box to be a reference to/or a class or box type value"); + "expect box to be a reference to a class or box type value"); if (getSource() && !fir::unwrapRefType(getSource().getType()).isa()) return emitOpError( diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index b719f677230ff59301b23888df8f82d5c09e70b3..4ca338066128768b0f5b5532997dd2fb7e871171 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -37,7 +37,7 @@ namespace fir { #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir -#define DEBUG_TYPE "flang-add-debug-foundation" +#define DEBUG_TYPE "flang-add-debug-info" namespace { diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp index 2cb15437a235ae927c3a0856a6c1733a3576660c..fb1ebadd3785864acb8c4b3d77023d49f8763220 100644 --- a/flang/lib/Semantics/check-cuda.cpp +++ b/flang/lib/Semantics/check-cuda.cpp @@ -488,6 +488,10 @@ void CUDAChecker::Enter(const parser::AssignmentStmt &x) { } const evaluate::Assignment *assign{semantics::GetAssignment(x)}; + if (!assign) { + return; + } + int nbLhs{evaluate::GetNbOfCUDASymbols(assign->lhs)}; int nbRhs{evaluate::GetNbOfCUDASymbols(assign->rhs)}; diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 824f1b6053ca392c622186ede62d885789b3759c..875929e90fdd3186c5ad20e9c886a7276b690782 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -1042,9 +1042,10 @@ void CheckHelper::CheckObjectEntity( parser::ToUpperCaseLetters(common::EnumToString(attr))); } } else if (!subpDetails && symbol.owner().kind() != Scope::Kind::Module && - symbol.owner().kind() != Scope::Kind::MainProgram) { + symbol.owner().kind() != Scope::Kind::MainProgram && + symbol.owner().kind() != Scope::Kind::BlockConstruct) { messages_.Say( - "ATTRIBUTES(%s) may apply only to module, host subprogram, or device subprogram data"_err_en_US, + "ATTRIBUTES(%s) may apply only to module, host subprogram, block, or device subprogram data"_err_en_US, parser::ToUpperCaseLetters(common::EnumToString(attr))); } } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index bafa242a79302a388ba94a8099c92ed11d208298..56653aa74f0cc55552b86319ade416ccb2748cf4 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2286,6 +2286,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { CheckReductionTypeList(x); } } + bool OmpStructureChecker::CheckReductionOperators( const parser::OmpClause::Reduction &x) { @@ -2356,6 +2357,16 @@ void OmpStructureChecker::CheckReductionTypeList( if (llvm::omp::nestedReduceWorkshareAllowedSet.test(GetContext().directive)) { CheckSharedBindingInOuterContext(ompObjectList); } + + SymbolSourceMap symbols; + GetSymbolsInObjectList(ompObjectList, symbols); + for (auto &[symbol, source] : symbols) { + if (IsProcedurePointer(*symbol)) { + context_.Say(source, + "A procedure pointer '%s' must not appear in a REDUCTION clause."_err_en_US, + symbol->name()); + } + } } void OmpStructureChecker::CheckIntentInPointerAndDefinable( diff --git a/flang/runtime/extensions.cpp b/flang/runtime/extensions.cpp index 12498b502ae1cf46e62fe5371aa3bd034f8153b7..4b110cc10c840e853f5f31b8ae69f1b1e51f48b7 100644 --- a/flang/runtime/extensions.cpp +++ b/flang/runtime/extensions.cpp @@ -43,9 +43,9 @@ inline void CtimeBuffer(char *buffer, size_t bufsize, const time_t cur_time, } #endif -#if _REENTRANT || _POSIX_C_SOURCE >= 199506L -// System is posix-compliant and has getlogin_r -#include +#ifndef _WIN32 +// posix-compliant and has getlogin_r and F_OK +#include #endif extern "C" { diff --git a/flang/test/Fir/cuf-invalid.fir b/flang/test/Fir/cuf-invalid.fir index 5d3aa55cf346a468586130e38446c5e737cf83f5..6c533a32ccf9bad4d5c1adc604337017b3c7a721 100644 --- a/flang/test/Fir/cuf-invalid.fir +++ b/flang/test/Fir/cuf-invalid.fir @@ -16,7 +16,7 @@ func.func @_QPsub1() { func.func @_QPsub1() { %1 = fir.alloca i32 - // expected-error@+1{{'fir.cuda_allocate' op expect box to be a reference to/or a class or box type value}} + // expected-error@+1{{'fir.cuda_allocate' op expect box to be a reference to a class or box type value}} %2 = fir.cuda_allocate %1 : !fir.ref {cuda_attr = #fir.cuda} -> i32 return } diff --git a/flang/test/Lower/CUDA/cuda-allocatable.cuf b/flang/test/Lower/CUDA/cuda-allocatable.cuf new file mode 100644 index 0000000000000000000000000000000000000000..5b10334ecdbc14c7cb79a5918b7d8879daa412a8 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-allocatable.cuf @@ -0,0 +1,122 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +! Test lowering of CUDA allocatable allocate/deallocate statements. + +subroutine sub1() + real, allocatable, device :: a(:) + allocate(a(10)) + + deallocate(a) +end subroutine + +! CHECK-LABEL: func.func @_QPsub1() +! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub1Ea"} +! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %[[BOX]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub1Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: fir.call @_FortranAAllocatableSetBounds +! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 + +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 + +subroutine sub2() + real, allocatable, managed :: a(:) + integer :: istat + allocate(a(10), stat=istat) + + deallocate(a, stat=istat) +end subroutine + +! CHECK-LABEL: func.func @_QPsub2() +! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub2Ea"} +! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %[[BOX]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub2Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[ISTAT:.*]] = fir.alloca i32 {bindc_name = "istat", uniq_name = "_QFsub2Eistat"} +! CHECK: %[[ISTAT_DECL:.*]]:2 = hlfir.declare %[[ISTAT]] {uniq_name = "_QFsub2Eistat"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.call @_FortranAAllocatableSetBounds +! CHECK: %[[STAT:.*]] = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda, hasStat} -> i32 +! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref + +! CHECK: %[[STAT:.*]] = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda, hasStat} -> i32 +! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref + +subroutine sub3() + integer, allocatable, pinned :: a(:,:) + logical :: plog + allocate(a(20,30), pinned = plog) +end subroutine + +! CHECK-LABEL: func.func @_QPsub3() +! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub3Ea"} +! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %[[BOX]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub3Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[PLOG:.*]] = fir.alloca !fir.logical<4> {bindc_name = "plog", uniq_name = "_QFsub3Eplog"} +! CHECK: %[[PLOG_DECL:.*]]:2 = hlfir.declare %5 {uniq_name = "_QFsub3Eplog"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK-2: fir.call @_FortranAAllocatableSetBounds +! 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(:) + 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: %[[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 + +subroutine sub5() + real, allocatable, device :: a(:) + real, allocatable :: b(:) + allocate(a, source=b) +end subroutine + +! CHECK-LABEL: func.func @_QPsub5() +! CHECK: %[[BOX_A:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub5Ea"} +! CHECK: %[[BOX_A_DECL:.*]]:2 = hlfir.declare %[[BOX]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub5Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[BOX_B:.*]] = fir.alloca !fir.box>> {bindc_name = "b", uniq_name = "_QFsub5Eb"} +! CHECK: %[[BOX_B_DECL:.*]]:2 = hlfir.declare %[[BOX_B]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub5Eb"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[LOAD_B:.*]] = fir.load %[[BOX_B_DECL]]#1 : !fir.ref>>> +! CHECK: fir.call @_FortranAAllocatableSetBounds +! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_A_DECL]]#1 : !fir.ref>>> source(%[[LOAD_B]] : !fir.box>>) {cuda_attr = #fir.cuda} -> i32 + +subroutine sub6() + real, allocatable, device :: a(:) + real, allocatable :: b(:) + allocate(a, mold=b) +end subroutine + +! CHECK-LABEL: func.func @_QPsub6() +! CHECK: %[[BOX_A:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub6Ea"} +! CHECK: %[[BOX_A_DECL:.*]]:2 = hlfir.declare %[[BOX]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub6Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[BOX_B:.*]] = fir.alloca !fir.box>> {bindc_name = "b", uniq_name = "_QFsub6Eb"} +! CHECK: %[[BOX_B_DECL:.*]]:2 = hlfir.declare %[[BOX_B]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub6Eb"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[LOAD_B:.*]] = fir.load %[[BOX_B_DECL]]#1 : !fir.ref>>> +! CHECK: fir.call @_FortranAAllocatableApplyMold +! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 + +subroutine sub7() + real, allocatable, device :: a(:) + integer :: istat + character(50) :: err + allocate(a(100), stat=istat, errmsg=err) + + deallocate(a, stat=istat, errmsg=err) +end subroutine + +! CHECK-LABEL: func.func @_QPsub7() +! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub7Ea"} +! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %[[BOX]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub7Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[ERR:.*]] = fir.alloca !fir.char<1,50> {bindc_name = "err", uniq_name = "_QFsub7Eerr"} +! CHECK: %[[ERR_DECL:.*]]:2 = hlfir.declare %[[ERR]] typeparams %{{.*}} {uniq_name = "_QFsub7Eerr"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[ISTAT:.*]] = fir.alloca i32 {bindc_name = "istat", uniq_name = "_QFsub7Eistat"} +! CHECK: %[[ISTAT_DECL:.*]]:2 = hlfir.declare %[[ISTAT]] {uniq_name = "_QFsub7Eistat"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[ERR_BOX:.*]] = fir.embox %[[ERR_DECL]]#1 : (!fir.ref>) -> !fir.box> +! CHECK: fir.call @_FortranAAllocatableSetBounds +! CHECK: %[[STAT:.*]] = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> errmsg(%[[ERR_BOX]] : !fir.box>) {cuda_attr = #fir.cuda, hasStat} -> i32 +! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref + +! CHECK: %[[ERR_BOX:.*]] = fir.embox %[[ERR_DECL]]#1 : (!fir.ref>) -> !fir.box> +! CHECK: %[[STAT:.*]] = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> errmsg(%15 : !fir.box>) {cuda_attr = #fir.cuda, hasStat} -> i32 +! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref diff --git a/flang/test/Semantics/OpenMP/reduction12.f90 b/flang/test/Semantics/OpenMP/reduction12.f90 new file mode 100644 index 0000000000000000000000000000000000000000..f896ca4aa60b678437737c78f15caaf3c9017459 --- /dev/null +++ b/flang/test/Semantics/OpenMP/reduction12.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp + +! OpenMP 5.2: Section 5.5.5 : A procedure pointer must not appear in a +! reduction clause. + + procedure(foo), pointer :: ptr + integer :: i + ptr => foo +!ERROR: A procedure pointer 'ptr' must not appear in a REDUCTION clause. +!$omp do reduction (+ : ptr) + do i = 1, 10 + end do +contains + subroutine foo + end subroutine +end diff --git a/flang/test/Semantics/cuf03.cuf b/flang/test/Semantics/cuf03.cuf index 574add9faaade729b7e39d33bf94f18ba65eee7c..8decb8dcaa0f47125b7375abf46f55a29668dd77 100644 --- a/flang/test/Semantics/cuf03.cuf +++ b/flang/test/Semantics/cuf03.cuf @@ -85,6 +85,11 @@ module m real, unified :: ru ! ok type(t1), unified :: tu ! ok type(t2) :: t ! ok + + block + real, device :: a(100) ! ok + end block end subroutine + end module diff --git a/flang/test/Semantics/cuf11.cuf b/flang/test/Semantics/cuf11.cuf index b915c7246ed94766bacd4d7c2d5481978aa50526..de7ff29743242b6cbc4b7c015a152116115a96e0 100644 --- a/flang/test/Semantics/cuf11.cuf +++ b/flang/test/Semantics/cuf11.cuf @@ -22,3 +22,11 @@ subroutine sub1() ahost = adev + adev end subroutine + +logical function compare_h(a,b) +!ERROR: Derived type 'h' not found + type(h) :: a, b +!ERROR: 'a' is not an object of derived type; it is implicitly typed +!ERROR: 'b' is not an object of derived type; it is implicitly typed + compare_h = (a%h .eq. b%h) +end diff --git a/flang/test/Semantics/cuf12.cuf b/flang/test/Semantics/cuf12.cuf new file mode 100644 index 0000000000000000000000000000000000000000..1b79c9889dfeaf0c642843082f120c81972a0f90 --- /dev/null +++ b/flang/test/Semantics/cuf12.cuf @@ -0,0 +1,8 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 + +program test + real, device :: b(100) ! ok + block + real, device :: a(100) ! ok + end block +end program diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index f33f9430c7920587036ef2e0f03a932fc156d6c7..4e3d1cb9f5337a74054f9583881d743b547c2dd1 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -201,6 +201,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index dad187fa0496d336e743553b4c895601501e7de7..7efd9bcd5b3cb85e76d219c25af0ed5c4b47b601 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -201,6 +201,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt index aea2f6d5771e877dadd6b2582655524a10aa4bc6..e1303265b9ac41eaa4f04fa7d75b0c1f9d72573b 100644 --- a/libc/config/darwin/arm/entrypoints.txt +++ b/libc/config/darwin/arm/entrypoints.txt @@ -112,6 +112,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt index 09fe3d7b4768701aaff047b4f953305a8538b7d9..02912decadcf79db703c41a31d1d4cd656bb3214 100644 --- a/libc/config/darwin/x86_64/entrypoints.txt +++ b/libc/config/darwin/x86_64/entrypoints.txt @@ -106,6 +106,7 @@ set(TARGET_LIBM_ENTRYPOINTS # libc.src.fenv.fesetround # libc.src.fenv.feraiseexcept # libc.src.fenv.fetestexcept + # libc.src.fenv.fetestexceptflag # libc.src.fenv.feupdateenv ## Currently disabled for failing tests. diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 2952baacdd67fd69ad67af0c3e8628201c8b68d9..1ac6bd93000082d659422feca45c50cffc2cec44 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -324,6 +324,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index 9964971f191b75e8eeaa1948df72b3e9e6b96460..5fb92a9c299cc3537acd92e953fdcc31e5a968f7 100644 --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -175,6 +175,7 @@ def PThreadAPI : PublicAPI<"pthread.h"> { "__pthread_start_t", "__pthread_tss_dtor_t", "pthread_attr_t", + "pthread_condattr_t", "pthread_mutex_t", "pthread_mutexattr_t", "pthread_t", @@ -241,10 +242,30 @@ def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> { } def SysTypesAPI : PublicAPI<"sys/types.h"> { - let Types = ["blkcnt_t", "blksize_t", "clockid_t", "dev_t", "gid_t", "ino_t", - "mode_t", "nlink_t", "off_t", "pid_t", "pthread_attr_t", "pthread_key_t", - "pthread_mutex_t", "pthread_mutexattr_t", "pthread_once_t", "pthread_t", - "size_t", "ssize_t", "suseconds_t", "time_t", "uid_t"]; + let Types = [ + "blkcnt_t", + "blksize_t", + "clockid_t", + "dev_t", + "gid_t", + "ino_t", + "mode_t", + "nlink_t", + "off_t", + "pid_t", + "pthread_attr_t", + "pthread_condattr_t", + "pthread_key_t", + "pthread_mutex_t", + "pthread_mutexattr_t", + "pthread_once_t", + "pthread_t", + "size_t", + "ssize_t", + "suseconds_t", + "time_t", + "uid_t" + ]; } def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> { diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 35fd588a9a6c4d42b5e2ec8f26a87330e377efa0..335981ff7dc7cf1446796aeb6fc0f4b8a9f64212 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -192,6 +192,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 47c03a61c45a9332685064e57639b2f9cf70505b..87e82e5eb9a067ec1ec6f347553d775c433825c4 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -332,6 +332,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 8fdd4575e27e28279093421e9f0b4cc68248db5c..2d8136536b218b145e7cf5325e9ec61c983044b2 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -346,6 +346,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints @@ -638,6 +639,12 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.pthread.pthread_attr_setguardsize libc.src.pthread.pthread_attr_setstack libc.src.pthread.pthread_attr_setstacksize + 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 libc.src.pthread.pthread_create libc.src.pthread.pthread_detach libc.src.pthread.pthread_equal diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index c46c947bf31354919678eb62512ddf2a59c5ba0f..71216530c4041b07f45fdbb2442dfcc52cd950f0 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -110,6 +110,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.fenv.fesetround libc.src.fenv.feraiseexcept libc.src.fenv.fetestexcept + libc.src.fenv.fetestexceptflag libc.src.fenv.feupdateenv # math.h entrypoints diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst index 4138c9d7104f337ebbc3045bfba786d54d41edfa..44724fe1660cbeb5017c6ad878154c9c45884d31 100644 --- a/libc/docs/c23.rst +++ b/libc/docs/c23.rst @@ -21,7 +21,7 @@ Additions: * fenv.h * fesetexcept |check| - * fetestexceptflag + * fetestexceptflag |check| * fegetmode * fesetmode * math.h diff --git a/libc/docs/contributing.rst b/libc/docs/contributing.rst index b92575ed4108f57a3ff49d5a9af65f6475f04100..bd7d9d79be57d72594f5110de124366ca9544ec8 100644 --- a/libc/docs/contributing.rst +++ b/libc/docs/contributing.rst @@ -9,6 +9,14 @@ to the libc project should also follow the general LLVM `contribution guidelines `_. Below is a list of open projects that one can start with: +#. **Beginner Bugs** - Help us tackle + `good first issues `__. + These bugs have been tagged with the github labels "libc" and "good first + issue" by the team as potentially easier places to get started. Please do + first check if the bug has an assignee; if so please find another unless + there's been no movement on the issue from the assignee, in which place do + ask if you can help take over. + #. **Cleanup code-style** - The libc project follows the general `LLVM style `_ but differs in a few aspects: We use ``snake_case`` for non-constant variable and function diff --git a/libc/docs/dev/config_options.rst b/libc/docs/dev/config_options.rst index 47f4baef8ebf1a2d4773d198c99c557a4d07b7c4..6392c853becf47bb52eed6767fe985f5011ed394 100644 --- a/libc/docs/dev/config_options.rst +++ b/libc/docs/dev/config_options.rst @@ -11,15 +11,14 @@ hierarchical JSON files. At the top of the hierarchy is a JSON file by name options which affect all platforms. The default value for the option and a short description about it listed against each option. For example: -.. code-block:: +.. code-block:: json { "printf": { "LIBC_CONF_PRINTF_DISABLE_FLOAT": { "value": false, "doc": "Disable printing floating point values in printf and friends." - }, - ... + } } } @@ -28,7 +27,7 @@ has a value of ``false``. A platform, say the baremetal platform, can choose to override this value in its ``config.json`` file in the ``config/baremetal`` directory with the following contents: -.. code-block:: +.. code-block:: json { "printf": { @@ -61,14 +60,13 @@ The value corresponding to each grouping tag is also a dictionary called the options belonging to that grouping tag. For the ``printf`` tag in the above example, the option-dictionary is: -.. code-block:: +.. code-block:: json { "LIBC_CONF_PRINTF_DISABLE_FLOAT": { "value": false, "doc": - }, - ... + } } The value corresponding to an option key in the option-dictionary is another @@ -86,7 +84,7 @@ Option name format The option names, or the keys of a option-dictionary, have the following format: -.. code-block:: +.. code-block:: none LIBC_CONF__ @@ -123,7 +121,7 @@ should convert the CMake config options to appropriate compiler and/or linker flags. Those compile/link flags can be used in listing the affected targets as follows: -.. code-block:: +.. code-block:: cmake add_object_library( ... diff --git a/libc/docs/fenv.rst b/libc/docs/fenv.rst index 6574fb7246ddd2d7b18f55f5a4f10a8943f3cb69..1dee5515e1174b463d0f519c17eb53ccc6293b74 100644 --- a/libc/docs/fenv.rst +++ b/libc/docs/fenv.rst @@ -42,7 +42,7 @@ fenv.h Functions - |check| - 7.6.6.3 * - fesetexcept - - + - |check| - 7.6.4.4 * - fesetexceptflag - |check| @@ -57,7 +57,7 @@ fenv.h Functions - |check| - 7.6.4.7 * - fetestexceptflag - - + - |check| - 7.6.4.6 * - feupdateenv - |check| diff --git a/libc/docs/index.rst b/libc/docs/index.rst index 11d5ae197d7189119f86f7ee9dd409343781fc4a..f71920b058d83f297cafe71e37e5aed6f9f4e5b5 100644 --- a/libc/docs/index.rst +++ b/libc/docs/index.rst @@ -71,6 +71,7 @@ stages there is no ABI stability in any form. c23 ctype signal + threads .. toctree:: :hidden: diff --git a/libc/docs/threads.rst b/libc/docs/threads.rst new file mode 100644 index 0000000000000000000000000000000000000000..78e17e9fdec3aaee389946141fc0e3b7e2f251f8 --- /dev/null +++ b/libc/docs/threads.rst @@ -0,0 +1,88 @@ +.. include:: check.rst + +threads.h Functions +=================== + +.. list-table:: + :widths: auto + :align: center + :header-rows: 1 + + * - Function + - Implemented + - Standard + * - call_once + - |check| + - 7.28.2.1 + * - cnd_broadcast + - |check| + - 7.28.3.1 + * - cnd_destroy + - |check| + - 7.28.3.2 + * - cnd_init + - |check| + - 7.28.3.3 + * - cnd_signal + - |check| + - 7.28.3.4 + * - cnd_timedwait + - + - 7.28.3.5 + * - cnd_wait + - |check| + - 7.28.3.6 + * - mtx_destroy + - |check| + - 7.28.4.1 + * - mtx_init + - |check| + - 7.28.4.2 + * - mtx_lock + - |check| + - 7.28.4.3 + * - mtx_timedlock + - + - 7.28.4.4 + * - mtx_trylock + - + - 7.28.4.5 + * - mtx_unlock + - |check| + - 7.28.4.6 + * - thrd_create + - |check| + - 7.28.5.1 + * - thrd_current + - |check| + - 7.28.5.2 + * - thrd_detach + - |check| + - 7.28.5.3 + * - thrd_equal + - |check| + - 7.28.5.4 + * - thrd_exit + - |check| + - 7.28.5.5 + * - thrd_join + - |check| + - 7.28.5.6 + * - thrd_sleep + - + - 7.28.5.7 + * - thrd_yield + - + - 7.28.5.8 + * - tss_create + - |check| + - 7.28.6.1 + * - tss_delete + - |check| + - 7.28.6.2 + * - tss_get + - |check| + - 7.28.6.3 + * - tss_set + - |check| + - 7.28.6.4 diff --git a/libc/examples/README.md b/libc/examples/README.md index 36b886090c6c1ce2dccd56311ade0afb0a09d278..1bc4a67294f2a7a1a12c33ee00d30a3498d70640 100644 --- a/libc/examples/README.md +++ b/libc/examples/README.md @@ -59,7 +59,7 @@ have installed them, you have to inform CMake that we are linking against the full libc as follows: ```bash -cmake ../ -G -DLIBC_FULLBUILD=ON \ +cmake ../ -G -DLLVM_LIBC_FULL_BUILD=ON \ -DCMAKE_SYSROOT= \ -DCMAKE_C_COMPILER=/bin/clang \ -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY diff --git a/libc/examples/examples.cmake b/libc/examples/examples.cmake index 81e99e3cbede9c84695d3c6b319dd1d80e8833df..6bb6b41c252f5b8e8b4c3f9da1c882a473dac75c 100644 --- a/libc/examples/examples.cmake +++ b/libc/examples/examples.cmake @@ -4,13 +4,13 @@ function(add_example name) ${ARGN} ) - if(LIBC_FULLBUILD) + if(LLVM_LIBC_FULL_BUILD) target_link_options(${name} PRIVATE -static -rtlib=compiler-rt -fuse-ld=lld) elseif(LIBC_OVERLAY_ARCHIVE_DIR) target_link_directories(${name} PRIVATE ${LIBC_OVERLAY_ARCHIVE_DIR}) target_link_options(${name} PRIVATE -l:libllvmlibc.a) else() - message(FATAL_ERROR "Either LIBC_FULLBUILD should be on or " + message(FATAL_ERROR "Either LLVM_LIBC_FULL_BUILD should be on or " "LIBC_OVERLAY_ARCHIVE_DIR should be set.") endif() endfunction() diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index b85366c8deafe019fa011ab630b6e03a99cf2e8a..f5ba2791af3fb8fb4b0fdb4e6e339f33bf89c911 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -321,6 +321,7 @@ add_gen_header( .llvm-libc-types.__pthread_start_t .llvm-libc-types.__pthread_tss_dtor_t .llvm-libc-types.pthread_attr_t + .llvm-libc-types.pthread_condattr_t .llvm-libc-types.pthread_mutex_t .llvm-libc-types.pthread_mutexattr_t .llvm-libc-types.pthread_t diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index 93a79e1477b337906346308e3b868eeae29fa9c9..f26fc0729dc94cbca0c3c70cacd370a3e90878a5 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -49,11 +49,12 @@ add_header(pid_t HDR pid_t.h) add_header(posix_spawn_file_actions_t HDR posix_spawn_file_actions_t.h) add_header(posix_spawnattr_t HDR posix_spawnattr_t.h) add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_t) +add_header(pthread_condattr_t HDR pthread_condattr_t.h DEPENDS .clockid_t) 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_t HDR pthread_t.h DEPENDS .__thread_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_t HDR pthread_t.h DEPENDS .__thread_type) add_header(rlim_t HDR rlim_t.h) add_header(time_t HDR time_t.h) add_header(stack_t HDR stack_t.h) diff --git a/libc/include/llvm-libc-types/pthread_condattr_t.h b/libc/include/llvm-libc-types/pthread_condattr_t.h new file mode 100644 index 0000000000000000000000000000000000000000..b91fc2950aa3f2993d8f03cb2562359ee6c7a5d5 --- /dev/null +++ b/libc/include/llvm-libc-types/pthread_condattr_t.h @@ -0,0 +1,18 @@ +//===-- Definition of pthread_condattr_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_CONDATTR_T_H +#define LLVM_LIBC_TYPES_PTHREAD_CONDATTR_T_H + +#include "clockid_t.h" + +typedef struct { + clockid_t clock; + int pshared; +} pthread_condattr_t; + +#endif // LLVM_LIBC_TYPES_PTHREAD_CONDATTR_T_H diff --git a/libc/include/pthread.h.def b/libc/include/pthread.h.def index abeb839ee83d16e77cfdc53485a27e0e691f66b2..a94d770657e1001ef8cdad217c4fd97dbc49f466 100644 --- a/libc/include/pthread.h.def +++ b/libc/include/pthread.h.def @@ -11,6 +11,9 @@ #include "__llvm-libc-common.h" +// TODO: move to a pthreads-macros.h file: +// https://github.com/llvm/llvm-project/issues/88997 + #define PTHREAD_STACK_MIN (1 << 14) // 16KB #define PTHREAD_MUTEX_INITIALIZER {0} @@ -32,6 +35,9 @@ enum { PTHREAD_MUTEX_ROBUST = 0x1, }; +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + %%public_api() #endif // LLVM_LIBC_PTHREAD_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 7095a3964ee3fbeb8a404245dddc078638838e4c..0c88dbd848a3fb99e03b07d03450621114a66bbd 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -26,6 +26,7 @@ def UidT : NamedType<"uid_t">; def GidT : NamedType<"gid_t">; def DevT : NamedType<"dev_t">; def ClockIdT : NamedType<"clockid_t">; +def RestrictedClockIdTPtr : RestrictedPtrType; def BlkSizeT : NamedType<"blksize_t">; def BlkCntT : NamedType<"blkcnt_t">; def NLinkT : NamedType<"nlink_t">; @@ -105,6 +106,10 @@ def POSIX : StandardSpec<"POSIX"> { ConstType ConstPThreadAttrTPtr = ConstType; ConstType ConstRestrictedPThreadAttrTPtr = ConstType; + NamedType PThreadCondAttrTType = NamedType<"pthread_condattr_t">; + PtrType PThreadCondAttrTPtr = PtrType; + ConstType ConstRestrictedPThreadCondAttrTPtr = ConstType>; + NamedType PThreadMutexAttrTType = NamedType<"pthread_mutexattr_t">; PtrType PThreadMutexAttrTPtr = PtrType; RestrictedPtrType RestrictedPThreadMutexAttrTPtr = RestrictedPtrType; @@ -980,7 +985,9 @@ def POSIX : StandardSpec<"POSIX"> { [], // Macros [ AtForkCallbackT, + ClockIdT, PThreadAttrTType, + PThreadCondAttrTType, PThreadKeyT, PThreadMutexAttrTType, PThreadMutexTType, @@ -1047,6 +1054,36 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, + FunctionSpec< + "pthread_condattr_destroy", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "pthread_condattr_getclock", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "pthread_condattr_getpshared", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "pthread_condattr_init", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "pthread_condattr_setclock", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "pthread_condattr_setpshared", + RetValSpec, + [ArgSpec, ArgSpec] + >, FunctionSpec< "pthread_create", RetValSpec, @@ -1522,9 +1559,30 @@ def POSIX : StandardSpec<"POSIX"> { HeaderSpec SysTypes = HeaderSpec< "sys/types.h", [], // Macros - [BlkCntT, BlkSizeT, ClockIdT, DevT, GidT, InoT, ModeTType, NLinkT, OffTType, PidT, - PThreadAttrTType, PThreadKeyT, PThreadMutexTType, PThreadMutexAttrTType, PThreadOnceT, PThreadTType, - SizeTType, SSizeTType, SuSecondsT, TimeTType, UidT], + [ + BlkCntT, + BlkSizeT, + ClockIdT, + DevT, + GidT, + InoT, + ModeTType, + NLinkT, + OffTType, + PThreadAttrTType, + PThreadCondAttrTType, + PThreadKeyT, + PThreadMutexAttrTType, + PThreadMutexTType, + PThreadOnceT, + PThreadTType, + PidT, + SSizeTType, + SizeTType, + SuSecondsT, + TimeTType, + UidT + ], // Types [], // Enumerations [] // Functions >; diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 63d0449867114d6cf871e7c0f6528b3e6f52a4d1..01aa7c70b3b9df73125ec180b4cb46f6eb638547 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -149,6 +149,11 @@ def StdC : StandardSpec<"stdc"> { RetValSpec, [ArgSpec] >, + FunctionSpec< + "fetestexceptflag", + RetValSpec, + [ArgSpec, ArgSpec] + >, FunctionSpec< "feraiseexcept", RetValSpec, diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h index 4be1a57f0f4b38f61f0f3d124635546074638ff0..13e668becc651a57c39da566940fcc9cf52c8263 100644 --- a/libc/src/__support/FPUtil/FEnvImpl.h +++ b/libc/src/__support/FPUtil/FEnvImpl.h @@ -9,11 +9,12 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FENVIMPL_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FENVIMPL_H +#include "hdr/fenv_macros.h" #include "hdr/math_macros.h" +#include "hdr/types/fenv_t.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/properties/architectures.h" #include "src/errno/libc_errno.h" -#include #if defined(LIBC_TARGET_ARCH_IS_AARCH64) #if defined(__APPLE__) diff --git a/libc/src/__support/FPUtil/riscv/FEnvImpl.h b/libc/src/__support/FPUtil/riscv/FEnvImpl.h index 6e940453f7a94dbfd5c6a30fd216ab66b6f8d5c9..e7aee3ba4b910993289aef4a3e5eaaf0f8c9c267 100644 --- a/libc/src/__support/FPUtil/riscv/FEnvImpl.h +++ b/libc/src/__support/FPUtil/riscv/FEnvImpl.h @@ -15,7 +15,6 @@ #include "src/__support/macros/attributes.h" // For LIBC_INLINE_ASM #include "src/__support/macros/config.h" // For LIBC_INLINE -#include #include namespace LIBC_NAMESPACE { diff --git a/libc/src/fenv/CMakeLists.txt b/libc/src/fenv/CMakeLists.txt index 17e994741206270c5dd524800956e3b6a17e7bec..c5431b1b9d55e0b7ddd5309a07f154ee95376ad9 100644 --- a/libc/src/fenv/CMakeLists.txt +++ b/libc/src/fenv/CMakeLists.txt @@ -58,6 +58,19 @@ add_entrypoint_object( -O2 ) +add_entrypoint_object( + fetestexceptflag + SRCS + fetestexceptflag.cpp + HDRS + fetestexceptflag.h + DEPENDS + libc.hdr.types.fexcept_t + libc.src.__support.FPUtil.fenv_impl + COMPILE_OPTIONS + -O2 +) + add_entrypoint_object( fegetenv SRCS diff --git a/libc/src/fenv/fetestexceptflag.cpp b/libc/src/fenv/fetestexceptflag.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63453350a199f5f6a83aa07feb1f7b27a581303d --- /dev/null +++ b/libc/src/fenv/fetestexceptflag.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of fetestexceptflag function -----------------------===// +// +// 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 "src/fenv/fetestexceptflag.h" +#include "hdr/types/fexcept_t.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, fetestexceptflag, + (const fexcept_t *flagp, int excepts)) { + static_assert(sizeof(int) >= sizeof(fexcept_t), + "fexcept_t value cannot fit in an int value."); + return *flagp | fputil::test_except(excepts); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/fenv/fetestexceptflag.h b/libc/src/fenv/fetestexceptflag.h new file mode 100644 index 0000000000000000000000000000000000000000..1c8b0b843f5477797bc42cc6911f526843c61e72 --- /dev/null +++ b/libc/src/fenv/fetestexceptflag.h @@ -0,0 +1,20 @@ +//===-- Implementation header for fetestexceptflag --------------*- 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_FENV_FETESTEXCEPTFLAG_H +#define LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H + +#include "hdr/types/fexcept_t.h" + +namespace LIBC_NAMESPACE { + +int fetestexceptflag(const fexcept_t *, int excepts); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt index d5e6c802a8452360e5f51aa649cb6662ed959806..3d6cf6dde010b1d776e9278a9dc769812b7d7ad5 100644 --- a/libc/src/pthread/CMakeLists.txt +++ b/libc/src/pthread/CMakeLists.txt @@ -100,6 +100,71 @@ add_entrypoint_object( libc.src.pthread.pthread_attr_setstacksize ) +add_entrypoint_object( + pthread_condattr_destroy + SRCS + pthread_condattr_destroy.cpp + HDRS + pthread_condattr_destroy.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_condattr_getclock + SRCS + pthread_condattr_getclock.cpp + HDRS + pthread_condattr_getclock.h + DEPENDS + libc.include.pthread + libc.include.sys_types +) + +add_entrypoint_object( + pthread_condattr_getpshared + SRCS + pthread_condattr_getpshared.cpp + HDRS + pthread_condattr_getpshared.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_condattr_init + SRCS + pthread_condattr_init.cpp + HDRS + pthread_condattr_init.h + DEPENDS + libc.include.pthread + libc.include.time +) + +add_entrypoint_object( + pthread_condattr_setclock + SRCS + pthread_condattr_setclock.cpp + HDRS + pthread_condattr_setclock.h + DEPENDS + libc.include.errno + libc.include.pthread + libc.include.sys_types + libc.include.time +) + +add_entrypoint_object( + pthread_condattr_setpshared + SRCS + pthread_condattr_setpshared.cpp + HDRS + pthread_condattr_setpshared.h + DEPENDS + libc.include.pthread +) + add_header_library( pthread_mutexattr HDRS diff --git a/libc/src/pthread/pthread_condattr_destroy.cpp b/libc/src/pthread/pthread_condattr_destroy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41994c6941ffe3d21187e92349f0cfa38ed8cdee --- /dev/null +++ b/libc/src/pthread/pthread_condattr_destroy.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of the pthread_condattr_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_condattr_destroy.h" + +#include "src/__support/common.h" + +#include + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_condattr_destroy, + (pthread_condattr_t * attr [[gnu::unused]])) { + // Initializing a pthread_condattr_t acquires no resources, so this is a + // no-op. + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_condattr_destroy.h b/libc/src/pthread/pthread_condattr_destroy.h new file mode 100644 index 0000000000000000000000000000000000000000..2910fa9f96168af24333e7f90ba038ee1c76089b --- /dev/null +++ b/libc/src/pthread/pthread_condattr_destroy.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_condattr_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_CONDATTR_DESTROY_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_DESTROY_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_condattr_destroy(pthread_condattr_t *attr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_DESTROY_H diff --git a/libc/src/pthread/pthread_condattr_getclock.cpp b/libc/src/pthread/pthread_condattr_getclock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3a3963f4f429e04a4a90416910e3e94faf3b17a --- /dev/null +++ b/libc/src/pthread/pthread_condattr_getclock.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of the pthread_condattr_getclock -------------------===// +// +// 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_condattr_getclock.h" + +#include "src/__support/common.h" + +#include // pthread_condattr_t +#include // clockid_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_condattr_getclock, + (const pthread_condattr_t *__restrict attr, + clockid_t *__restrict clock_id)) { + *clock_id = attr->clock; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_condattr_getclock.h b/libc/src/pthread/pthread_condattr_getclock.h new file mode 100644 index 0000000000000000000000000000000000000000..d5878c4f45b537334bc48fcecaefe480a4530462 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_getclock.h @@ -0,0 +1,22 @@ +//===-- Implementation header for pthread_condattr_getclock -----*- 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_CONDATTR_GETCLOCK_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_GETCLOCK_H + +#include // pthread_condattr_t +#include // clockid_t + +namespace LIBC_NAMESPACE { + +int pthread_condattr_getclock(const pthread_condattr_t *__restrict attr, + clockid_t *__restrict clock_id); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_GETCLOCK_H diff --git a/libc/src/pthread/pthread_condattr_getpshared.cpp b/libc/src/pthread/pthread_condattr_getpshared.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c5fdc115c25d75c53acc3437460b96a2538c542 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_getpshared.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of the pthread_condattr_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_condattr_getpshared.h" + +#include "src/__support/common.h" + +#include + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_condattr_getpshared, + (const pthread_condattr_t *__restrict attr, + int *__restrict pshared)) { + *pshared = attr->pshared; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_condattr_getpshared.h b/libc/src/pthread/pthread_condattr_getpshared.h new file mode 100644 index 0000000000000000000000000000000000000000..3d7a0c1d357c60aec13d5decb14dcadeab40adf4 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_getpshared.h @@ -0,0 +1,21 @@ +//===-- Implementation header for pthread_condattr_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_CONDATTR_PSHARED_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_PSHARED_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_condattr_getpshared(const pthread_condattr_t *__restrict attr, + int *__restrict pshared); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_PSHARED_H diff --git a/libc/src/pthread/pthread_condattr_init.cpp b/libc/src/pthread/pthread_condattr_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54633b2e3a5eafc803982307bb9b410a9ef622a0 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_init.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of the pthread_condattr_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_condattr_init.h" + +#include "src/__support/common.h" + +#include // pthread_condattr_t, PTHREAD_PROCESS_PRIVATE +#include // CLOCK_REALTIME + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_condattr_init, (pthread_condattr_t * attr)) { + attr->clock = CLOCK_REALTIME; + attr->pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_condattr_init.h b/libc/src/pthread/pthread_condattr_init.h new file mode 100644 index 0000000000000000000000000000000000000000..9f3c06bb6f4aef53d4763cec547edf63d000ec56 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_init.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_condattr_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_CONDATTR_INIT_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_INIT_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_condattr_init(pthread_condattr_t *attr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_INIT_H diff --git a/libc/src/pthread/pthread_condattr_setclock.cpp b/libc/src/pthread/pthread_condattr_setclock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6eca8b30ef7f8ea4b5a89855ba3259e509059919 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_setclock.cpp @@ -0,0 +1,30 @@ +//===-- Implementation of the pthread_condattr_setclock -------------------===// +// +// 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_condattr_setclock.h" + +#include "src/__support/common.h" + +#include // EINVAL +#include // pthread_condattr_t +#include // clockid_t +#include // CLOCK_MONOTONIC, CLOCK_REALTIME + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_condattr_setclock, + (pthread_condattr_t * attr, clockid_t clock)) { + + if (clock != CLOCK_MONOTONIC && clock != CLOCK_REALTIME) + return EINVAL; + + attr->clock = clock; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_condattr_setclock.h b/libc/src/pthread/pthread_condattr_setclock.h new file mode 100644 index 0000000000000000000000000000000000000000..328766fe7883368efc78eada89cf30d3145caad8 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_setclock.h @@ -0,0 +1,21 @@ +//===-- Implementation header for pthread_condattr_setclock -----*- 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_CONDATTR_SETCLOCK_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_SETCLOCK_H + +#include +#include // clockid_t + +namespace LIBC_NAMESPACE { + +int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_SETCLOCK_H diff --git a/libc/src/pthread/pthread_condattr_setpshared.cpp b/libc/src/pthread/pthread_condattr_setpshared.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f1560acad843e2871988023b3553d2b198bf74c --- /dev/null +++ b/libc/src/pthread/pthread_condattr_setpshared.cpp @@ -0,0 +1,28 @@ +//===-- Implementation of the pthread_condattr_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_condattr_setpshared.h" + +#include "src/__support/common.h" + +#include // EINVAL +#include // pthread_condattr_t, PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_condattr_setpshared, + (pthread_condattr_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_condattr_setpshared.h b/libc/src/pthread/pthread_condattr_setpshared.h new file mode 100644 index 0000000000000000000000000000000000000000..8083bdec78cc47b4b0df2175c0d53630d37db524 --- /dev/null +++ b/libc/src/pthread/pthread_condattr_setpshared.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_condattr_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_CONDATTR_SETPSHARED_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_SETPSHARED_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_CONDATTR_SETPSHARED_H diff --git a/libc/src/unistd/linux/pipe.cpp b/libc/src/unistd/linux/pipe.cpp index b4e8b9b7d9c85e6423dc64a1a9cb7351b414deb1..8cfb8d1d5c2c139ba02c5fcd2dd4529ba23c9e60 100644 --- a/libc/src/unistd/linux/pipe.cpp +++ b/libc/src/unistd/linux/pipe.cpp @@ -10,6 +10,7 @@ #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" +#include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON #include "src/errno/libc_errno.h" #include // For syscall numbers. @@ -23,6 +24,7 @@ LLVM_LIBC_FUNCTION(int, pipe, (int pipefd[2])) { int ret = LIBC_NAMESPACE::syscall_impl( SYS_pipe2, reinterpret_cast(pipefd), 0); #endif + MSAN_UNPOISON(pipefd, sizeof(int) * 2); if (ret < 0) { libc_errno = -ret; return -1; diff --git a/libc/test/src/fenv/CMakeLists.txt b/libc/test/src/fenv/CMakeLists.txt index 577735599dc010eba11968f747d043a3321d16c4..f277b65e2d42be01f971aad967b9c2f8b3e58022 100644 --- a/libc/test/src/fenv/CMakeLists.txt +++ b/libc/test/src/fenv/CMakeLists.txt @@ -48,6 +48,7 @@ add_libc_unittest( DEPENDS libc.src.fenv.fegetexceptflag libc.src.fenv.fesetexceptflag + libc.src.fenv.fetestexceptflag libc.src.__support.FPUtil.fenv_impl ) diff --git a/libc/test/src/fenv/exception_flags_test.cpp b/libc/test/src/fenv/exception_flags_test.cpp index d1d8bfcc53db567991422eaf4417261d66acf5bf..9d2be6426a6d0b734a84f946fce9845610f49f6d 100644 --- a/libc/test/src/fenv/exception_flags_test.cpp +++ b/libc/test/src/fenv/exception_flags_test.cpp @@ -1,4 +1,4 @@ -//===-- Unittests for fegetexceptflag and fesetexceptflag -----------------===// +//===-- Unittests for fe{get|set|test}exceptflag --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,11 +9,12 @@ #include "hdr/types/fexcept_t.h" #include "src/fenv/fegetexceptflag.h" #include "src/fenv/fesetexceptflag.h" +#include "src/fenv/fetestexceptflag.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "test/UnitTest/Test.h" -TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) { +TEST(LlvmLibcFenvTest, GetSetTestExceptFlag) { // We will disable all exceptions to prevent invocation of the exception // handler. LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT); @@ -39,19 +40,36 @@ TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) { ASSERT_EQ(LIBC_NAMESPACE::fesetexceptflag(&eflags, FE_ALL_EXCEPT), 0); ASSERT_NE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & e, 0); + // Exception flags are exactly the flags corresponding to the previously + // raised exception. + ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&eflags, FE_ALL_EXCEPT), + LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT)); + // Cleanup. We clear all excepts as raising excepts like FE_OVERFLOW // can also raise FE_INEXACT. LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); } - // Next, we will raise one exception and save the flags. + // Next, we will raise one exception, save the flag and clear all exceptions. LIBC_NAMESPACE::fputil::raise_except(FE_INVALID); - fexcept_t eflags; - LIBC_NAMESPACE::fegetexceptflag(&eflags, FE_ALL_EXCEPT); - // Clear all exceptions and raise two other exceptions. + fexcept_t invalid_flag; + LIBC_NAMESPACE::fegetexceptflag(&invalid_flag, FE_ALL_EXCEPT); + ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&invalid_flag, FE_ALL_EXCEPT), + FE_INVALID); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + + // Raise two other exceptions and verify that they are set. LIBC_NAMESPACE::fputil::raise_except(FE_OVERFLOW | FE_INEXACT); + fexcept_t overflow_and_inexact_flag; + LIBC_NAMESPACE::fegetexceptflag(&overflow_and_inexact_flag, FE_ALL_EXCEPT); + ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&overflow_and_inexact_flag, + FE_ALL_EXCEPT), + FE_OVERFLOW | FE_INEXACT); + ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&overflow_and_inexact_flag, + FE_OVERFLOW | FE_INEXACT), + FE_OVERFLOW | FE_INEXACT); + // When we set the flags and test, we should only see FE_INVALID. - LIBC_NAMESPACE::fesetexceptflag(&eflags, FE_ALL_EXCEPT); + LIBC_NAMESPACE::fesetexceptflag(&invalid_flag, FE_ALL_EXCEPT); EXPECT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT), FE_INVALID); } diff --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt index fb0d22ab9d2a57bd0c11c6082993f59c82c77ad4..51954a5babd2c589747647a9fdfe1996c086f224 100644 --- a/libc/test/src/pthread/CMakeLists.txt +++ b/libc/test/src/pthread/CMakeLists.txt @@ -39,3 +39,21 @@ add_libc_unittest( libc.src.pthread.pthread_mutexattr_setrobust libc.src.pthread.pthread_mutexattr_settype ) + +add_libc_unittest( + pthread_condattr_test + SUITE + libc_pthread_unittests + SRCS + pthread_condattr_test.cpp + DEPENDS + libc.include.errno + 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 + ) diff --git a/libc/test/src/pthread/pthread_condattr_test.cpp b/libc/test/src/pthread/pthread_condattr_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..accb62de92e45ff9a802089a8374d8603bac6106 --- /dev/null +++ b/libc/test/src/pthread/pthread_condattr_test.cpp @@ -0,0 +1,71 @@ +//===-- Unittests for pthread_condattr_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 "test/UnitTest/Test.h" + +#include +#include +#include + +TEST(LlvmLibcPThreadCondAttrTest, InitAndDestroy) { + pthread_condattr_t cond; + ASSERT_EQ(pthread_condattr_init(&cond), 0); + ASSERT_EQ(pthread_condattr_destroy(&cond), 0); +} + +TEST(LlvmLibcPThreadCondAttrTest, GetDefaultValues) { + pthread_condattr_t cond; + + // Invalid clock id. + clockid_t clock = 7; + // Invalid value. + int pshared = 42; + + ASSERT_EQ(pthread_condattr_init(&cond), 0); + ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(clock, CLOCK_REALTIME); + ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(pthread_condattr_destroy(&cond), 0); +} + +TEST(LlvmLibcPThreadCondAttrTest, SetGoodValues) { + pthread_condattr_t cond; + + // Invalid clock id. + clockid_t clock = 7; + // 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(clock, CLOCK_MONOTONIC); + ASSERT_EQ(pthread_condattr_setpshared(&cond, PTHREAD_PROCESS_SHARED), 0); + ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); + ASSERT_EQ(pthread_condattr_destroy(&cond), 0); +} + +TEST(LlvmLibcPThreadCondAttrTest, SetBadValues) { + pthread_condattr_t cond; + + // Invalid clock id. + clockid_t clock = 7; + // 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(clock, CLOCK_REALTIME); + ASSERT_EQ(pthread_condattr_setpshared(&cond, pshared), EINVAL); + ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(pthread_condattr_destroy(&cond), 0); +} diff --git a/libc/utils/docgen/fenv.json b/libc/utils/docgen/fenv.json index 0af38b16b2d982e98473fe7426f0db33b20b1b6c..9aa3f641ddc94b1525331b0cc65b399ef4a3c4d9 100644 --- a/libc/utils/docgen/fenv.json +++ b/libc/utils/docgen/fenv.json @@ -1,7 +1,63 @@ { - "macros": [ - "__STDC_VERSION_FENV_H__" - ], + "macros": { + "__STDC_VERSION_FENV_H__": { + "defined": "7.6.5" + }, + "FE_DIVBYZERO": { + "defined": "7.6.9" + }, + "FE_INEXACT": { + "defined": "7.6.9" + }, + "FE_INVALID": { + "defined": "7.6.9" + }, + "FE_OVERFLOW": { + "defined": "7.6.9" + }, + "FE_UNDERFLOW": { + "defined": "7.6.9" + }, + "FE_ALL_EXCEPT": { + "defined": "7.6.12" + }, + "FE_DFL_MODE": { + "defined": "7.6.11" + }, + "FE_DOWNARD": { + "defined": "7.6.13" + }, + "FE_TONEAREST": { + "defined": "7.6.13" + }, + "FE_TONEARESTFROMZERO": { + "defined": "7.6.13" + }, + "FE_TOWARDZERO": { + "defined": "7.6.13" + }, + "FE_UPWARD": { + "defined": "7.6.13" + }, + "FE_DEC_DOWNWARD": { + "defined": "7.6.14" + }, + "FE_DEC_TONEAREST": { + "defined": "7.6.14" + }, + "FE_DEC_TONEARESTFROMZERO": { + "defined": "7.6.14" + }, + "FE_DEC_TOWARDZERO": { + "defined": "7.6.14" + }, + "FE_DEC_UPWARD": { + "defined": "7.6.14" + }, + "FE_DFL_ENV": { + "defined": "7.6.17" + } + }, "functions": { "feclearexcept": { "defined": "7.6.4.1" diff --git a/libc/utils/docgen/signal.json b/libc/utils/docgen/signal.json index 976021a803a672e8de60b86dbec481453ce19915..d5380d348b7d66d791c5cd6c7f1bf40ccd0a600c 100644 --- a/libc/utils/docgen/signal.json +++ b/libc/utils/docgen/signal.json @@ -1,16 +1,40 @@ { - "macros": [ - "SIG_DFL", - "SIG_ERR", - "SIG_IGN", - "SIGABRT", - "SIGFPE", - "SIGILL", - "SIGINT", - "SIGSEGV", - "SIGTERM" - ], + "macros": { + "SIG_DFL": { + "defined": "7.14.3" + }, + "SIG_ERR": { + "defined": "7.14.3" + }, + "SIG_IGN": { + "defined": "7.14.3" + }, + "SIGABRT": { + "defined": "7.14.3" + }, + "SIGFPE": { + "defined": "7.14.3" + }, + "SIGILL": { + "defined": "7.14.3" + }, + "SIGINT": { + "defined": "7.14.3" + }, + "SIGSEGV": { + "defined": "7.14.3" + }, + "SIGTERM": { + "defined": "7.14.3" + } + }, "functions": { + "signal": { + "defined": "7.14.1.1" + }, + "raise": { + "defined": "7.14.2.1" + }, "kill": null, "sigaction": null, "sigaddset": null, @@ -18,12 +42,6 @@ "sigdelset": null, "sigemptyset": null, "sigfillset": null, - "sigprocmask": null, - "signal": { - "defined": "7.14.1.1" - }, - "raise": { - "defined": "7.14.2.1" - } + "sigprocmask": null } } diff --git a/libc/utils/docgen/stdbit.json b/libc/utils/docgen/stdbit.json index 9dda0cb0f5383ac269a4a58e21c0b47cf9fe287a..88106cf0e4f97bf487a7cbde86119a16d96a3abe 100644 --- a/libc/utils/docgen/stdbit.json +++ b/libc/utils/docgen/stdbit.json @@ -1,24 +1,60 @@ { - "macros": [ - "__STDC_VERSION_STDBIT_H__", - "__STDC_ENDIAN_LITTLE__", - "__STDC_ENDIAN_BIG__", - "__STDC_ENDIAN_NATIVE__", - "stdc_leading_zeros", - "stdc_leading_ones", - "stdc_trailing_zeros", - "stdc_trailing_ones", - "stdc_first_leading_zero", - "stdc_first_leading_one", - "stdc_first_trailing_zero", - "stdc_first_trailing_one", - "stdc_count_zeros", - "stdc_count_ones", - "stdc_has_single_bit", - "stdc_bit_width", - "stdc_bit_floor", - "stdc_bit_ceil" - ], + "macros": { + "__STDC_VERSION_STDBIT_H__": { + "defined": "7.18.1.2" + }, + "__STDC_ENDIAN_LITTLE__": { + "defined": "7.18.2.2" + }, + "__STDC_ENDIAN_BIG__": { + "defined": "7.18.2.2" + }, + "__STDC_ENDIAN_NATIVE__": { + "defined": "7.18.2.2" + }, + "stdc_leading_zeros": { + "defined": "7.18.3.1" + }, + "stdc_leading_ones": { + "defined": "7.18.4.1" + }, + "stdc_trailing_zeros": { + "defined": "7.18.5.1" + }, + "stdc_trailing_ones": { + "defined": "7.18.6.1" + }, + "stdc_first_leading_zero": { + "defined": "7.18.7.1" + }, + "stdc_first_leading_one": { + "defined": "7.18.8.1" + }, + "stdc_first_trailing_zero": { + "defined": "7.18.9.1" + }, + "stdc_first_trailing_one": { + "defined": "7.18.10.1" + }, + "stdc_count_zeros": { + "defined": "7.18.11.1" + }, + "stdc_count_ones": { + "defined": "7.18.12.1" + }, + "stdc_has_single_bit": { + "defined": "7.18.13.1" + }, + "stdc_bit_width": { + "defined": "7.18.14.1" + }, + "stdc_bit_floor": { + "defined": "7.18.15.1" + }, + "stdc_bit_ceil": { + "defined": "7.18.16.1" + } + }, "functions": { "stdc_leading_zeros_uc": { "defined": "7.18.3" diff --git a/libc/utils/docgen/threads.json b/libc/utils/docgen/threads.json new file mode 100644 index 0000000000000000000000000000000000000000..aef6ffaf75bae3ebff8373b3c89a2d55449409df --- /dev/null +++ b/libc/utils/docgen/threads.json @@ -0,0 +1,87 @@ +{ + "macros": { + "ONCE_FLAG_INIT": { + "defined": "7.28.1.3" + }, + "TSS_DTOR_ITERATIONS": { + "defined": "7.28.1.3" + } + }, + "functions": { + "call_once": { + "defined": "7.28.2.1" + }, + "cnd_broadcast": { + "defined": "7.28.3.1" + }, + "cnd_destroy": { + "defined": "7.28.3.2" + }, + "cnd_init": { + "defined": "7.28.3.3" + }, + "cnd_signal": { + "defined": "7.28.3.4" + }, + "cnd_timedwait": { + "defined": "7.28.3.5" + }, + "cnd_wait": { + "defined": "7.28.3.6" + }, + "mtx_destroy": { + "defined": "7.28.4.1" + }, + "mtx_init": { + "defined": "7.28.4.2" + }, + "mtx_lock": { + "defined": "7.28.4.3" + }, + "mtx_timedlock": { + "defined": "7.28.4.4" + }, + "mtx_trylock": { + "defined": "7.28.4.5" + }, + "mtx_unlock": { + "defined": "7.28.4.6" + }, + "thrd_create": { + "defined": "7.28.5.1" + }, + "thrd_current": { + "defined": "7.28.5.2" + }, + "thrd_detach": { + "defined": "7.28.5.3" + }, + "thrd_equal": { + "defined": "7.28.5.4" + }, + "thrd_exit": { + "defined": "7.28.5.5" + }, + "thrd_join": { + "defined": "7.28.5.6" + }, + "thrd_sleep": { + "defined": "7.28.5.7" + }, + "thrd_yield": { + "defined": "7.28.5.8" + }, + "tss_create": { + "defined": "7.28.6.1" + }, + "tss_delete": { + "defined": "7.28.6.2" + }, + "tss_get": { + "defined": "7.28.6.3" + }, + "tss_set": { + "defined": "7.28.6.4" + } + } +} diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index f605c3bbbe9dce3663e2e1f0e6f7b31d027984b9..5ce17952430854158d8a8adec6055d939a99c41a 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -32,7 +32,7 @@ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS set( LIBCLC_MIN_LLVM 3.9.0 ) set( LIBCLC_TARGETS_TO_BUILD "all" - CACHE STRING "Semicolon-separated list of targets to build, or 'all'." ) + CACHE STRING "Semicolon-separated list of libclc targets to build, or 'all'." ) option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." OFF ) @@ -50,11 +50,13 @@ if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DI endif() # Import required tools as targets - foreach( tool IN ITEMS clang llvm-as llvm-link opt ) - find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) - add_executable( libclc::${tool} IMPORTED GLOBAL ) - set_target_properties( libclc::${tool} PROPERTIES IMPORTED_LOCATION ${LLVM_TOOL_${tool}} ) - endforeach() + if( NOT EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} ) + foreach( tool IN ITEMS clang llvm-as llvm-link opt ) + find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) + add_executable( libclc::${tool} IMPORTED GLOBAL ) + set_target_properties( libclc::${tool} PROPERTIES IMPORTED_LOCATION ${LLVM_TOOL_${tool}} ) + endforeach() + endif() else() # In-tree configuration set( LIBCLC_STANDALONE_BUILD FALSE ) @@ -68,19 +70,44 @@ else() message(FATAL_ERROR "Clang is not enabled, but is required to build libclc in-tree") endif() + if( NOT EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} ) + foreach( tool IN ITEMS clang llvm-as llvm-link opt ) + add_executable(libclc::${tool} ALIAS ${tool}) + endforeach() + endif() +endif() + +if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} ) + message( WARNING "Using custom LLVM tools to build libclc: " + "${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR}, " + " ensure the tools are up to date." ) + # Note - use a differently named variable than LLVM_TOOL_${tool} as above, as + # the variable name is used to cache the result of find_program. If we used + # the same name, a user wouldn't be able to switch a build between default + # and custom tools. foreach( tool IN ITEMS clang llvm-as llvm-link opt ) - add_executable(libclc::${tool} ALIAS ${tool}) + find_program( LLVM_CUSTOM_TOOL_${tool} ${tool} + PATHS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) + add_executable( libclc::${tool} IMPORTED GLOBAL ) + set_target_properties( libclc::${tool} PROPERTIES + IMPORTED_LOCATION ${LLVM_CUSTOM_TOOL_${tool}} ) endforeach() endif() -if( NOT TARGET libclc::clang OR NOT TARGET libclc::opt - OR NOT TARGET libclc::llvm-as OR NOT TARGET libclc::llvm-link ) - message( FATAL_ERROR "libclc toolchain incomplete!" ) -endif() +foreach( tool IN ITEMS clang opt llvm-as llvm-link ) + if( NOT TARGET libclc::${tool} ) + message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" ) + endif() +endforeach() # llvm-spirv is an optional dependency, used to build spirv-* targets. find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) +if( LLVM_SPIRV ) + add_executable( libclc::llvm-spirv IMPORTED GLOBAL ) + set_target_properties( libclc::llvm-spirv PROPERTIES IMPORTED_LOCATION ${LLVM_SPIRV} ) +endif() + # List of all targets. Note that some are added dynamically below. set( LIBCLC_TARGETS_ALL amdgcn-- @@ -101,7 +128,7 @@ endif() # spirv-mesa3d and spirv64-mesa3d targets can only be built with the (optional) # llvm-spirv external tool. -if( LLVM_SPIRV ) +if( TARGET libclc::llvm-spirv ) list( APPEND LIBCLC_TARGETS_ALL spirv-mesa3d- spirv64-mesa3d- ) endif() @@ -114,7 +141,7 @@ list( SORT LIBCLC_TARGETS_TO_BUILD ) # Verify that the user hasn't requested mesa3d targets without an available # llvm-spirv tool. if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD ) - if( NOT LLVM_SPIRV ) + if( NOT TARGET libclc::llvm-spirv ) message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not installed" ) endif() endif() @@ -363,7 +390,7 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) if( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 ) set( spv_suffix ${arch_suffix}.spv ) add_custom_command( OUTPUT ${spv_suffix} - COMMAND ${LLVM_SPIRV} ${spvflags} -o ${spv_suffix} ${builtins_link_lib} + COMMAND libclc::llvm-spirv ${spvflags} -o ${spv_suffix} ${builtins_link_lib} DEPENDS ${builtins_link_lib} ) add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" ) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 043d5a8295c1a6ce590b20458b26ffb6d94dce4a..2977c26646cb2e27df0908282b487c73e3d7e8ca 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -300,9 +300,9 @@ option(LIBCXX_HAS_EXTERNAL_THREAD_API This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON." OFF) if (LIBCXX_ENABLE_THREADS) - set(LIBCXX_PSTL_CPU_BACKEND "std_thread" CACHE STRING "Which PSTL CPU backend to use") + set(LIBCXX_PSTL_BACKEND "std_thread" CACHE STRING "Which PSTL backend to use") else() - set(LIBCXX_PSTL_CPU_BACKEND "serial" CACHE STRING "Which PSTL CPU backend to use") + set(LIBCXX_PSTL_BACKEND "serial" CACHE STRING "Which PSTL backend to use") endif() # Misc options ---------------------------------------------------------------- @@ -792,14 +792,14 @@ elseif (LIBCXX_HARDENING_MODE STREQUAL "debug") config_define(8 _LIBCPP_HARDENING_MODE_DEFAULT) endif() -if (LIBCXX_PSTL_CPU_BACKEND STREQUAL "serial") - config_define(1 _LIBCPP_PSTL_CPU_BACKEND_SERIAL) -elseif(LIBCXX_PSTL_CPU_BACKEND STREQUAL "std_thread") - config_define(1 _LIBCPP_PSTL_CPU_BACKEND_THREAD) -elseif(LIBCXX_PSTL_CPU_BACKEND STREQUAL "libdispatch") - config_define(1 _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +if (LIBCXX_PSTL_BACKEND STREQUAL "serial") + config_define(1 _LIBCPP_PSTL_BACKEND_SERIAL) +elseif(LIBCXX_PSTL_BACKEND STREQUAL "std_thread") + config_define(1 _LIBCPP_PSTL_BACKEND_STD_THREAD) +elseif(LIBCXX_PSTL_BACKEND STREQUAL "libdispatch") + config_define(1 _LIBCPP_PSTL_BACKEND_LIBDISPATCH) else() - message(FATAL_ERROR "LIBCXX_PSTL_CPU_BACKEND is set to ${LIBCXX_PSTL_CPU_BACKEND}, which is not a valid backend. + message(FATAL_ERROR "LIBCXX_PSTL_BACKEND is set to ${LIBCXX_PSTL_BACKEND}, which is not a valid backend. Valid backends are: serial, std_thread and libdispatch") endif() diff --git a/libcxx/cmake/caches/Apple.cmake b/libcxx/cmake/caches/Apple.cmake index cec13c08acf107a5c47ece7ab988d53807997b85..8768653e620add32a6aa59a913c019cd54160ebf 100644 --- a/libcxx/cmake/caches/Apple.cmake +++ b/libcxx/cmake/caches/Apple.cmake @@ -7,7 +7,7 @@ set(LIBCXX_ENABLE_STATIC ON CACHE BOOL "") set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "") set(LIBCXX_CXX_ABI libcxxabi CACHE STRING "") set(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS ON CACHE BOOL "") -set(LIBCXX_PSTL_CPU_BACKEND libdispatch CACHE STRING "") +set(LIBCXX_PSTL_BACKEND libdispatch CACHE STRING "") set(LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") set(LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv index e9d407e79e25397382bf2e71071130e62ea0c589..f29f1f7ca74875d599428a394b19940fc540c64f 100644 --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -24,8 +24,8 @@ Section,Description,Dependencies,Assignee,Status,First released version `[time.syn] `_,"Formatter ``chrono::year_month_weekday``",,Mark de Wever,|Complete|,16.0 `[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|,16.0 `[time.syn] `_,"Formatter ``chrono::hh_mm_ss>``",,Mark de Wever,|Complete|,17.0 -`[time.syn] `_,"Formatter ``chrono::sys_info``",A ```` implementation,Mark de Wever,, -`[time.syn] `_,"Formatter ``chrono::local_info``",A ```` implementation,Mark de Wever,, +`[time.syn] `_,"Formatter ``chrono::sys_info``",,Mark de Wever,|Complete|,19.0 +`[time.syn] `_,"Formatter ``chrono::local_info``",,Mark de Wever,|Complete|,19.0 `[time.syn] `_,"Formatter ``chrono::zoned_time``",A ```` implementation,Mark de Wever,, "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index a2af1d9915be40d0e7084344cc45c0c1364cdc8b..4ecd834c5382ae03335a533296e0e45609674f75 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -73,20 +73,6 @@ set(files __algorithm/pop_heap.h __algorithm/prev_permutation.h __algorithm/pstl_any_all_none_of.h - __algorithm/pstl_backend.h - __algorithm/pstl_backends/cpu_backend.h - __algorithm/pstl_backends/cpu_backends/any_of.h - __algorithm/pstl_backends/cpu_backends/backend.h - __algorithm/pstl_backends/cpu_backends/fill.h - __algorithm/pstl_backends/cpu_backends/find_if.h - __algorithm/pstl_backends/cpu_backends/for_each.h - __algorithm/pstl_backends/cpu_backends/libdispatch.h - __algorithm/pstl_backends/cpu_backends/merge.h - __algorithm/pstl_backends/cpu_backends/serial.h - __algorithm/pstl_backends/cpu_backends/stable_sort.h - __algorithm/pstl_backends/cpu_backends/thread.h - __algorithm/pstl_backends/cpu_backends/transform.h - __algorithm/pstl_backends/cpu_backends/transform_reduce.h __algorithm/pstl_copy.h __algorithm/pstl_count.h __algorithm/pstl_equal.h @@ -284,6 +270,7 @@ set(files __chrono/high_resolution_clock.h __chrono/leap_second.h __chrono/literals.h + __chrono/local_info.h __chrono/month.h __chrono/month_weekday.h __chrono/monthday.h @@ -594,7 +581,20 @@ set(files __numeric/transform_exclusive_scan.h __numeric/transform_inclusive_scan.h __numeric/transform_reduce.h + __pstl/backends/libdispatch.h + __pstl/backends/serial.h + __pstl/backends/std_thread.h + __pstl/configuration.h + __pstl/configuration_fwd.h + __pstl/cpu_algos/any_of.h __pstl/cpu_algos/cpu_traits.h + __pstl/cpu_algos/fill.h + __pstl/cpu_algos/find_if.h + __pstl/cpu_algos/for_each.h + __pstl/cpu_algos/merge.h + __pstl/cpu_algos/stable_sort.h + __pstl/cpu_algos/transform.h + __pstl/cpu_algos/transform_reduce.h __random/bernoulli_distribution.h __random/binomial_distribution.h __random/cauchy_distribution.h diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backend.h b/libcxx/include/__algorithm/pstl_backends/cpu_backend.h deleted file mode 100644 index 53eae58f9609523eb55d36c2c9e19996049952f3..0000000000000000000000000000000000000000 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backend.h +++ /dev/null @@ -1,23 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H - -#include <__algorithm/pstl_backends/cpu_backends/any_of.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__algorithm/pstl_backends/cpu_backends/fill.h> -#include <__algorithm/pstl_backends/cpu_backends/find_if.h> -#include <__algorithm/pstl_backends/cpu_backends/for_each.h> -#include <__algorithm/pstl_backends/cpu_backends/merge.h> -#include <__algorithm/pstl_backends/cpu_backends/stable_sort.h> -#include <__algorithm/pstl_backends/cpu_backends/transform.h> -#include <__algorithm/pstl_backends/cpu_backends/transform_reduce.h> -#include <__config> - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h deleted file mode 100644 index cb9425862a2b034cb110a1e10fe8aa661bf1b812..0000000000000000000000000000000000000000 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H - -#include <__config> -#include - -#if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) -# include <__algorithm/pstl_backends/cpu_backends/serial.h> -#elif defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) -# include <__algorithm/pstl_backends/cpu_backends/thread.h> -#elif defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) -# include <__algorithm/pstl_backends/cpu_backends/libdispatch.h> -#else -# error "Invalid CPU backend choice" -#endif - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -# if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) -using __cpu_backend_tag = __pstl::__serial_backend_tag; -# elif defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) -using __cpu_backend_tag = __pstl::__std_thread_backend_tag; -# elif defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) -using __cpu_backend_tag = __pstl::__libdispatch_backend_tag; -# endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H diff --git a/libcxx/include/__algorithm/pstl_copy.h b/libcxx/include/__algorithm/pstl_copy.h index f35bb9713ef1409996ce00fd198f75aa4d27eb10..0fcea33c3919f0becf2e2f13422ef92983a709ae 100644 --- a/libcxx/include/__algorithm/pstl_copy.h +++ b/libcxx/include/__algorithm/pstl_copy.h @@ -10,13 +10,13 @@ #define _LIBCPP___ALGORITHM_PSTL_COPY_H #include <__algorithm/copy_n.h> -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_transform.h> #include <__config> #include <__functional/identity.h> #include <__iterator/concepts.h> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_execution_policy.h> diff --git a/libcxx/include/__algorithm/pstl_count.h b/libcxx/include/__algorithm/pstl_count.h index 6ff57cac334eb058c0f5cbb6793529f3c61af355..64c84d855e4f61702e4cc7f547a4f6bf9dedc1fa 100644 --- a/libcxx/include/__algorithm/pstl_count.h +++ b/libcxx/include/__algorithm/pstl_count.h @@ -11,7 +11,6 @@ #include <__algorithm/count.h> #include <__algorithm/for_each.h> -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_for_each.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__atomic/atomic.h> @@ -20,6 +19,7 @@ #include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> #include <__numeric/pstl_transform_reduce.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_find.h b/libcxx/include/__algorithm/pstl_find.h index 3b30a7bc9b456f4460395e01c3442003df699822..b4c4dfb2ffb6f6b7ebe67f295a5f463ae7614567 100644 --- a/libcxx/include/__algorithm/pstl_find.h +++ b/libcxx/include/__algorithm/pstl_find.h @@ -11,10 +11,10 @@ #include <__algorithm/comp.h> #include <__algorithm/find.h> -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_for_each.h b/libcxx/include/__algorithm/pstl_for_each.h index a9ebed74a62fd4af2ae750c3259dbb9024527b25..a99eb6d97fd274f68941f8e27bf55fce5eb03fc2 100644 --- a/libcxx/include/__algorithm/pstl_for_each.h +++ b/libcxx/include/__algorithm/pstl_for_each.h @@ -11,11 +11,11 @@ #include <__algorithm/for_each.h> #include <__algorithm/for_each_n.h> -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_generate.h b/libcxx/include/__algorithm/pstl_generate.h index 886af290d7f25ad53e937d8a2e38c56f94a7d480..350c0e4798be67831377b1ff58275fd851f15519 100644 --- a/libcxx/include/__algorithm/pstl_generate.h +++ b/libcxx/include/__algorithm/pstl_generate.h @@ -9,12 +9,12 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_GENERATE_H #define _LIBCPP___ALGORITHM_PSTL_GENERATE_H -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_for_each.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> #include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_is_partitioned.h b/libcxx/include/__algorithm/pstl_is_partitioned.h index 108bb1e4325260c17188d578dde1a85617dace54..c016b388e3784a6aa660efd7722fe1fa03eb3c71 100644 --- a/libcxx/include/__algorithm/pstl_is_partitioned.h +++ b/libcxx/include/__algorithm/pstl_is_partitioned.h @@ -10,11 +10,11 @@ #define _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED #include <__algorithm/pstl_any_all_none_of.h> -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_find.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_merge.h b/libcxx/include/__algorithm/pstl_merge.h index d03cd8c7fbd5809354ea8e54f1f13a0d9a7a932d..87f634a67f5889d2ddfbfa56e93570501447de09 100644 --- a/libcxx/include/__algorithm/pstl_merge.h +++ b/libcxx/include/__algorithm/pstl_merge.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_MERGE_H #define _LIBCPP___ALGORITHM_PSTL_MERGE_H -#include <__algorithm/pstl_backend.h> #include <__config> #include <__functional/operations.h> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_move.h b/libcxx/include/__algorithm/pstl_move.h index f4c8c1fbb2e8760cfc2eac5c50faf1bcb104e582..3155ddedf91bb6a1cbe37028a8b6c545757eb01c 100644 --- a/libcxx/include/__algorithm/pstl_move.h +++ b/libcxx/include/__algorithm/pstl_move.h @@ -10,13 +10,13 @@ #define _LIBCPP___ALGORITHM_PSTL_MOVE_H #include <__algorithm/copy_n.h> -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_transform.h> #include <__config> #include <__functional/identity.h> #include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_execution_policy.h> diff --git a/libcxx/include/__algorithm/pstl_replace.h b/libcxx/include/__algorithm/pstl_replace.h index 73ac11cda26a9f32d122338efede6dac4aee6df8..b2ded54dfe25f3bbae387d98147eb28ff43ae861 100644 --- a/libcxx/include/__algorithm/pstl_replace.h +++ b/libcxx/include/__algorithm/pstl_replace.h @@ -9,13 +9,13 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_REPLACE_H #define _LIBCPP___ALGORITHM_PSTL_REPLACE_H -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_for_each.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_transform.h> #include <__config> #include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/remove_cvref.h> #include <__utility/move.h> diff --git a/libcxx/include/__algorithm/pstl_rotate_copy.h b/libcxx/include/__algorithm/pstl_rotate_copy.h index adab3958fe3112ed6dc8253c4d80a6c09c207b1e..1a32b710877c16b00ad77d3845660dba1761d58d 100644 --- a/libcxx/include/__algorithm/pstl_rotate_copy.h +++ b/libcxx/include/__algorithm/pstl_rotate_copy.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H #define _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_copy.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/is_execution_policy.h> #include diff --git a/libcxx/include/__algorithm/pstl_sort.h b/libcxx/include/__algorithm/pstl_sort.h index 65bc794ca6f4c8349f21cb3a702d0bfa56648ef5..769dd81af77e0493c49a6189d0a3c118e67511c8 100644 --- a/libcxx/include/__algorithm/pstl_sort.h +++ b/libcxx/include/__algorithm/pstl_sort.h @@ -9,12 +9,12 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_SORT_H #define _LIBCPP___ALGORITHM_PSTL_SORT_H -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_stable_sort.h> #include <__config> #include <__functional/operations.h> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> #include <__utility/empty.h> diff --git a/libcxx/include/__algorithm/pstl_stable_sort.h b/libcxx/include/__algorithm/pstl_stable_sort.h index 79b94557e3dc3aef9b357194fe3b82a8edec54b7..f5e0dd40f72b4709a7ded81cf7a44f9815f52351 100644 --- a/libcxx/include/__algorithm/pstl_stable_sort.h +++ b/libcxx/include/__algorithm/pstl_stable_sort.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H #define _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H -#include <__algorithm/pstl_backend.h> #include <__config> #include <__functional/operations.h> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__algorithm/pstl_transform.h b/libcxx/include/__algorithm/pstl_transform.h index a01a64a43cf1a33921716d815e08f71fcecec721..80e1d6b496f2ea6cd5c2ef63d906d54e9b32779b 100644 --- a/libcxx/include/__algorithm/pstl_transform.h +++ b/libcxx/include/__algorithm/pstl_transform.h @@ -9,9 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H #define _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H -#include <__algorithm/pstl_backend.h> #include <__config> #include <__iterator/cpp17_iterator_concepts.h> +#include <__pstl/configuration.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index 1301cd6f1f1ada504975e27f785978d46fcea753..f7256db3bea661101d5f5c2536fa21bbf1dce861 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -16,10 +16,12 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/statically_widen.h> +#include <__chrono/sys_info.h> #include <__chrono/system_clock.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> @@ -171,6 +173,12 @@ _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) + } else if constexpr (same_as<_ChronoT, chrono::sys_info>) { + // Has no time information. + } else if constexpr (same_as<_ChronoT, chrono::local_info>) { + // Has no time information. +# endif } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index d932a99f4b9983689644f2308440c50a5b80f3ad..6a14c344fa1188c0cbd71289d0562d93c6c6a1f2 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -18,12 +18,14 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/ostream.h> #include <__chrono/parser_std_format_spec.h> #include <__chrono/statically_widen.h> +#include <__chrono/sys_info.h> #include <__chrono/system_clock.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> @@ -186,10 +188,11 @@ __format_zone_offset(basic_stringstream<_CharT>& __sstr, chrono::seconds __offse chrono::hh_mm_ss __hms{__offset}; std::ostreambuf_iterator<_CharT> __out_it{__sstr}; + // Note HMS does not allow formatting hours > 23, but the offset is not limited to 24H. + std::format_to(__out_it, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __hms.hours().count()); if (__modifier) - std::format_to(__out_it, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:%H:%M}"), __hms); - else - std::format_to(__out_it, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:%H%M}"), __hms); + __sstr << _CharT(':'); + std::format_to(__out_it, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __hms.minutes().count()); } // Helper to store the time zone information needed for formatting. @@ -202,7 +205,12 @@ struct _LIBCPP_HIDE_FROM_ABI __time_zone { template _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const _Tp& __value) { - return {"UTC", chrono::seconds{0}}; +# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + if constexpr (same_as<_Tp, chrono::sys_info>) + return {__value.abbrev, __value.offset}; + else +# endif + return {"UTC", chrono::seconds{0}}; } template @@ -322,15 +330,13 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( __formatter::__format_year(__sstr, __t.tm_year + 1900); break; - case _CharT('F'): { - int __year = __t.tm_year + 1900; - if (__year < 1000) { - __formatter::__format_year(__sstr, __year); - __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); - } else - __facet.put( - {__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); - } break; + case _CharT('F'): + // Depending on the platform's libc the range of supported years is + // limited. Instead of testing all conditions use the internal + // implementation unconditionally. + __formatter::__format_year(__sstr, __t.tm_year + 1900); + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); + break; case _CharT('z'): __formatter::__format_zone_offset(__sstr, __z.__offset, false); @@ -411,6 +417,12 @@ _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) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -451,6 +463,12 @@ _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) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -491,6 +509,12 @@ _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) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -531,6 +555,12 @@ _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) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -860,6 +890,31 @@ public: return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time); } }; + +# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +template <__fmt_char_type _CharT> +struct formatter : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time_zone); + } +}; + +template <__fmt_char_type _CharT> +struct formatter : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags{}); + } +}; +# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + #endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__chrono/local_info.h b/libcxx/include/__chrono/local_info.h new file mode 100644 index 0000000000000000000000000000000000000000..b1a03ad7df2acab44fce1b44b04aff84ef372e97 --- /dev/null +++ b/libcxx/include/__chrono/local_info.h @@ -0,0 +1,50 @@ +// -*- 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 +// +//===----------------------------------------------------------------------===// + +// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html + +#ifndef _LIBCPP___CHRONO_LOCAL_INFO_H +#define _LIBCPP___CHRONO_LOCAL_INFO_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + +# include <__chrono/sys_info.h> +# include <__config> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 + +namespace chrono { + +struct local_info { + static constexpr int unique = 0; + static constexpr int nonexistent = 1; + static constexpr int ambiguous = 2; + + int result; + sys_info first; + sys_info second; +}; + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + +#endif // _LIBCPP___CHRONO_LOCAL_INFO_H diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h index b687ef8059d5f501d993c6e828accf8c66c96c49..cb17dbea58bee3606014379ac0c69596f92b0945 100644 --- a/libcxx/include/__chrono/ostream.h +++ b/libcxx/include/__chrono/ostream.h @@ -15,10 +15,12 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/statically_widen.h> +#include <__chrono/sys_info.h> #include <__chrono/system_clock.h> #include <__chrono/weekday.h> #include <__chrono/year.h> @@ -262,6 +264,46 @@ 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) + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __info) { + // __info.abbrev is always std::basic_string. + // Since these strings typically are short the conversion should be cheap. + std::basic_string<_CharT> __abbrev{__info.abbrev.begin(), __info.abbrev.end()}; + return __os << std::format( + _LIBCPP_STATICALLY_WIDEN(_CharT, "[{:%F %T}, {:%F %T}) {:%T} {:%Q%q} \"{}\""), + __info.begin, + __info.end, + hh_mm_ss{__info.offset}, + __info.save, + __abbrev); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __info) { + auto __result = [&]() -> basic_string<_CharT> { + switch (__info.result) { + case local_info::unique: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "unique"); + case local_info::nonexistent: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "non-existent"); + case local_info::ambiguous: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ambiguous"); + + default: + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "unspecified result ({})"), __info.result); + }; + }; + + return __os << std::format( + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}: {{{}, {}}}"), __result(), __info.first, __info.second); +} + +# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + } // namespace chrono #endif // if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__chrono/sys_info.h b/libcxx/include/__chrono/sys_info.h index 794d22f2ccc1ef0ec4d644c097aa7070780dc522..461d5322d413b3a4bf3c2ec2be2b41532f34f6b8 100644 --- a/libcxx/include/__chrono/sys_info.h +++ b/libcxx/include/__chrono/sys_info.h @@ -42,7 +42,7 @@ struct sys_info { } // namespace chrono -# endif //_LIBCPP_STD_VER >= 20 +# endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in index 7c002c5bfcf8e77f84e0cf14254b358d0896356f..89a14609ee3f92d7100c8c92a39b941fda326fa8 100644 --- a/libcxx/include/__config_site.in +++ b/libcxx/include/__config_site.in @@ -32,9 +32,9 @@ #cmakedefine _LIBCPP_INSTRUMENTED_WITH_ASAN // PSTL backends -#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_SERIAL -#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_THREAD -#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH +#cmakedefine _LIBCPP_PSTL_BACKEND_SERIAL +#cmakedefine _LIBCPP_PSTL_BACKEND_STD_THREAD +#cmakedefine _LIBCPP_PSTL_BACKEND_LIBDISPATCH // Hardening. #cmakedefine _LIBCPP_HARDENING_MODE_DEFAULT @_LIBCPP_HARDENING_MODE_DEFAULT@ diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h index 4924e5fb325336307ce179f5eadee662dbabdbbf..aa02f81dc40e2d8eb283047038448c6d68990946 100644 --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -19,6 +19,7 @@ #include <__fwd/format.h> #include <__memory/addressof.h> #include <__type_traits/conditional.h> +#include <__type_traits/remove_const.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/unreachable.h> diff --git a/libcxx/include/__numeric/pstl_transform_reduce.h b/libcxx/include/__numeric/pstl_transform_reduce.h index 2d2621dc8dadb1b7ab69651fe9945b840fc4d1c8..fe41b1c86f3b1f407f166b4b147b617756caebda 100644 --- a/libcxx/include/__numeric/pstl_transform_reduce.h +++ b/libcxx/include/__numeric/pstl_transform_reduce.h @@ -9,12 +9,12 @@ #ifndef _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H #define _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H -#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> #include <__functional/operations.h> #include <__iterator/cpp17_iterator_concepts.h> #include <__numeric/transform_reduce.h> +#include <__pstl/configuration.h> #include <__type_traits/is_execution_policy.h> #include <__utility/move.h> #include diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h b/libcxx/include/__pstl/backends/libdispatch.h similarity index 95% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h rename to libcxx/include/__pstl/backends/libdispatch.h index 17faadf55dd4fa64f478c8cfb4e9ab90da008e0c..af1da80dc133e514a0bedf7a6d478ca8335768a6 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h +++ b/libcxx/include/__pstl/backends/libdispatch.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H +#ifndef _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H +#define _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H #include <__algorithm/inplace_merge.h> #include <__algorithm/lower_bound.h> @@ -23,6 +23,7 @@ #include <__memory/construct_at.h> #include <__memory/unique_ptr.h> #include <__numeric/reduce.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__utility/empty.h> #include <__utility/exception_guard.h> @@ -40,8 +41,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD namespace __pstl { -struct __libdispatch_backend_tag {}; - namespace __libdispatch { // ::dispatch_apply is marked as __attribute__((nothrow)) because it doesn't let exceptions propagate, and neither do // we. @@ -349,4 +348,14 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H +// Implement PSTL algorithms based on the __cpu_traits specialized above +#include <__pstl/cpu_algos/any_of.h> +#include <__pstl/cpu_algos/fill.h> +#include <__pstl/cpu_algos/find_if.h> +#include <__pstl/cpu_algos/for_each.h> +#include <__pstl/cpu_algos/merge.h> +#include <__pstl/cpu_algos/stable_sort.h> +#include <__pstl/cpu_algos/transform.h> +#include <__pstl/cpu_algos/transform_reduce.h> + +#endif // _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h b/libcxx/include/__pstl/backends/serial.h similarity index 82% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h rename to libcxx/include/__pstl/backends/serial.h index 7544619a8eefd8411f064d30fad900156279dd3f..6e343313bea36aa5880fa2f48dabbba736531b8c 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h +++ b/libcxx/include/__pstl/backends/serial.h @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H +#ifndef _LIBCPP___PSTL_BACKENDS_SERIAL_H +#define _LIBCPP___PSTL_BACKENDS_SERIAL_H #include <__config> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__utility/empty.h> #include <__utility/move.h> @@ -29,8 +30,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD namespace __pstl { -struct __serial_backend_tag {}; - template <> struct __cpu_traits<__serial_backend_tag> { template @@ -82,4 +81,14 @@ _LIBCPP_POP_MACROS #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H +// Implement PSTL algorithms based on the __cpu_traits specialized above +#include <__pstl/cpu_algos/any_of.h> +#include <__pstl/cpu_algos/fill.h> +#include <__pstl/cpu_algos/find_if.h> +#include <__pstl/cpu_algos/for_each.h> +#include <__pstl/cpu_algos/merge.h> +#include <__pstl/cpu_algos/stable_sort.h> +#include <__pstl/cpu_algos/transform.h> +#include <__pstl/cpu_algos/transform_reduce.h> + +#endif // _LIBCPP___PSTL_BACKENDS_SERIAL_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h b/libcxx/include/__pstl/backends/std_thread.h similarity index 83% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h rename to libcxx/include/__pstl/backends/std_thread.h index 2acf912264a0015c43481952cb9f3398b7e18a14..e58f4859e6c9e3c7b1b6efc7c09859ecfe6b3e15 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h +++ b/libcxx/include/__pstl/backends/std_thread.h @@ -6,11 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H +#ifndef _LIBCPP___PSTL_BACKENDS_STD_THREAD_H +#define _LIBCPP___PSTL_BACKENDS_STD_THREAD_H #include <__assert> #include <__config> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__utility/empty.h> #include <__utility/move.h> @@ -32,8 +33,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD namespace __pstl { -struct __std_thread_backend_tag {}; - template <> struct __cpu_traits<__std_thread_backend_tag> { template @@ -85,4 +84,14 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H +// Implement PSTL algorithms based on the __cpu_traits specialized above +#include <__pstl/cpu_algos/any_of.h> +#include <__pstl/cpu_algos/fill.h> +#include <__pstl/cpu_algos/find_if.h> +#include <__pstl/cpu_algos/for_each.h> +#include <__pstl/cpu_algos/merge.h> +#include <__pstl/cpu_algos/stable_sort.h> +#include <__pstl/cpu_algos/transform.h> +#include <__pstl/cpu_algos/transform_reduce.h> + +#endif // _LIBCPP___PSTL_BACKENDS_STD_THREAD_H diff --git a/libcxx/include/__pstl/configuration.h b/libcxx/include/__pstl/configuration.h new file mode 100644 index 0000000000000000000000000000000000000000..d32bd21df1f9e5c4932d189f6832c2ac1cc04437 --- /dev/null +++ b/libcxx/include/__pstl/configuration.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___PSTL_CONFIGURATION_H +#define _LIBCPP___PSTL_CONFIGURATION_H + +#include <__config> +#include <__pstl/configuration_fwd.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if defined(_LIBCPP_PSTL_BACKEND_SERIAL) +# include <__pstl/backends/serial.h> +#elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) +# include <__pstl/backends/std_thread.h> +#elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) +# include <__pstl/backends/libdispatch.h> +#endif + +#endif // _LIBCPP___PSTL_CONFIGURATION_H diff --git a/libcxx/include/__algorithm/pstl_backend.h b/libcxx/include/__pstl/configuration_fwd.h similarity index 93% rename from libcxx/include/__algorithm/pstl_backend.h rename to libcxx/include/__pstl/configuration_fwd.h index 3af03ce2fbc8ee2510698603ff62c4917a29759f..995fcfce847cbca53ae41c692b462d5436b14bf6 100644 --- a/libcxx/include/__algorithm/pstl_backend.h +++ b/libcxx/include/__pstl/configuration_fwd.h @@ -6,10 +6,9 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKEND_H -#define _LIBCPP___ALGORITHM_PSTL_BACKEND_H +#ifndef _LIBCPP___PSTL_CONFIGURATION_FWD_H +#define _LIBCPP___PSTL_CONFIGURATION_FWD_H -#include <__algorithm/pstl_backends/cpu_backend.h> #include <__config> #include @@ -191,6 +190,20 @@ into a program termination at the front-end level. When a backend returns a dise frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to the user. */ +namespace __pstl { +struct __libdispatch_backend_tag {}; +struct __serial_backend_tag {}; +struct __std_thread_backend_tag {}; +} // namespace __pstl + +# if defined(_LIBCPP_PSTL_BACKEND_SERIAL) +using __cpu_backend_tag = __pstl::__serial_backend_tag; +# elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) +using __cpu_backend_tag = __pstl::__std_thread_backend_tag; +# elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) +using __cpu_backend_tag = __pstl::__libdispatch_backend_tag; +# endif + template struct __select_backend; @@ -206,8 +219,8 @@ struct __select_backend { }; # endif -# if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) || defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) || \ - defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +# if defined(_LIBCPP_PSTL_BACKEND_SERIAL) || defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) || \ + defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) template <> struct __select_backend { using type = __cpu_backend_tag; @@ -229,4 +242,4 @@ _LIBCPP_END_NAMESPACE_STD #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKEND_H +#endif // _LIBCPP___PSTL_CONFIGURATION_FWD_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h b/libcxx/include/__pstl/cpu_algos/any_of.h similarity index 93% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h rename to libcxx/include/__pstl/cpu_algos/any_of.h index 3755d288047e0b73d473f0ddddeb6cfac6e23d7d..01b9d214310a3336f2edb032ea8d63fef5755363 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h +++ b/libcxx/include/__pstl/cpu_algos/any_of.h @@ -6,17 +6,17 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H +#define _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H #include <__algorithm/any_of.h> #include <__algorithm/find_if.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__atomic/atomic.h> #include <__atomic/memory_order.h> #include <__config> #include <__functional/operations.h> #include <__iterator/concepts.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/move.h> @@ -96,4 +96,4 @@ _LIBCPP_POP_MACROS #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h b/libcxx/include/__pstl/cpu_algos/fill.h similarity index 90% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h rename to libcxx/include/__pstl/cpu_algos/fill.h index 0c20bdff62675afa276f1f96d9aa3d463453e8b4..66fb751eb7a2e66c770ac94ee9d02830760fba11 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h +++ b/libcxx/include/__pstl/cpu_algos/fill.h @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_FILL_H +#define _LIBCPP___PSTL_CPU_ALGOS_FILL_H #include <__algorithm/fill.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__config> #include <__iterator/concepts.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/empty.h> @@ -60,4 +60,4 @@ _LIBCPP_END_NAMESPACE_STD #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_FILL_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h b/libcxx/include/__pstl/cpu_algos/find_if.h similarity index 95% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h rename to libcxx/include/__pstl/cpu_algos/find_if.h index 626293faef6921acfc7a83434265e4e0fe30860b..c99ec01bff48f8b35b3f6da87ca5054579af17f6 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h +++ b/libcxx/include/__pstl/cpu_algos/find_if.h @@ -6,16 +6,16 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_FIND_IF_H +#define _LIBCPP___PSTL_CPU_ALGOS_FIND_IF_H #include <__algorithm/find_if.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__atomic/atomic.h> #include <__config> #include <__functional/operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/move.h> @@ -132,4 +132,4 @@ _LIBCPP_POP_MACROS #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_FIND_IF_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h b/libcxx/include/__pstl/cpu_algos/for_each.h similarity index 90% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h rename to libcxx/include/__pstl/cpu_algos/for_each.h index d637084e151d8118aa1361a6d51ec6501a7e66b5..cd7ce022469bd2ea73940c7f0519eb0a8268841d 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h +++ b/libcxx/include/__pstl/cpu_algos/for_each.h @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_FOR_EACH_H +#define _LIBCPP___PSTL_CPU_ALGOS_FOR_EACH_H #include <__algorithm/for_each.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__config> #include <__iterator/concepts.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/empty.h> @@ -60,4 +60,4 @@ _LIBCPP_END_NAMESPACE_STD #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_FOR_EACH_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h b/libcxx/include/__pstl/cpu_algos/merge.h similarity index 91% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h rename to libcxx/include/__pstl/cpu_algos/merge.h index c93f4051c9d094fafa5f55e06ba550283003ce23..b857fc1fb7a56d4e9c5bba60a2ef38da3052e1e9 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h +++ b/libcxx/include/__pstl/cpu_algos/merge.h @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_MERGE_H +#define _LIBCPP___PSTL_CPU_ALGOS_MERGE_H #include <__algorithm/merge.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__config> #include <__iterator/concepts.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/move.h> @@ -83,4 +83,4 @@ _LIBCPP_POP_MACROS #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_MERGE_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h b/libcxx/include/__pstl/cpu_algos/stable_sort.h similarity index 84% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h rename to libcxx/include/__pstl/cpu_algos/stable_sort.h index 8c60cf897ff860e7247e5ebc5309c7edefa37e17..18effb2108a2f78c2880db68fa9367885e8f83a7 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h +++ b/libcxx/include/__pstl/cpu_algos/stable_sort.h @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_STABLE_SORT_H +#define _LIBCPP___PSTL_CPU_ALGOS_STABLE_SORT_H -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/stable_sort.h> #include <__config> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/empty.h> @@ -43,4 +43,4 @@ _LIBCPP_END_NAMESPACE_STD #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_STABLE_SORT_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h b/libcxx/include/__pstl/cpu_algos/transform.h similarity index 95% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h rename to libcxx/include/__pstl/cpu_algos/transform.h index 4b9b2968668327a18ca5c96f3ded73997a78fa8c..70853dc9af24e0175674883bbf04a33007d01d71 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h +++ b/libcxx/include/__pstl/cpu_algos/transform.h @@ -6,14 +6,14 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_H +#define _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_H -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/transform.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> @@ -136,4 +136,4 @@ _LIBCPP_POP_MACROS #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__pstl/cpu_algos/transform_reduce.h similarity index 96% rename from libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h rename to libcxx/include/__pstl/cpu_algos/transform_reduce.h index c074eea9861c1b720127ca7721b26b4d585004af..a85ee9fb773afb0ee39218b71959494e3ac33a33 100644 --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h +++ b/libcxx/include/__pstl/cpu_algos/transform_reduce.h @@ -6,14 +6,14 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_REDUCE_H +#define _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_REDUCE_H -#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__numeric/transform_reduce.h> +#include <__pstl/configuration_fwd.h> #include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/desugars_to.h> #include <__type_traits/is_arithmetic.h> @@ -203,4 +203,4 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_REDUCE_H diff --git a/libcxx/include/__type_traits/remove_cv.h b/libcxx/include/__type_traits/remove_cv.h index 8e1c043364323595e4f8e120fe8e0c86d78d1f8d..2c4e9e419a1beca05e47588afac5cc310f9dd724 100644 --- a/libcxx/include/__type_traits/remove_cv.h +++ b/libcxx/include/__type_traits/remove_cv.h @@ -10,8 +10,6 @@ #define _LIBCPP___TYPE_TRAITS_REMOVE_CV_H #include <__config> -#include <__type_traits/remove_const.h> -#include <__type_traits/remove_volatile.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/chrono b/libcxx/include/chrono index 513ae52006e8903919abf1358a4363249e784524..96a3e92faa81f21efa2547244d43f7d464eb5ced 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -733,6 +733,24 @@ struct sys_info { string abbrev; }; +template // C++20 + basic_ostream& + operator<<(basic_ostream& os, const sys_info& si); + +struct local_info { // C++20 + static constexpr int unique = 0; + static constexpr int nonexistent = 1; + static constexpr int ambiguous = 2; + + int result; + sys_info first; + sys_info second; +}; + +template // C++20 + basic_ostream& + operator<<(basic_ostream& os, const local_info& li); + // 25.10.5, class time_zone // C++20 enum class choose {earliest, latest}; class time_zone { @@ -829,6 +847,8 @@ namespace std { template struct formatter; // C++20 template struct formatter>, charT>; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 } // namespace std namespace chrono { @@ -894,6 +914,7 @@ constexpr chrono::year operator ""y(unsigned lo # include <__chrono/day.h> # include <__chrono/hh_mm_ss.h> # include <__chrono/literals.h> +# include <__chrono/local_info.h> # include <__chrono/month.h> # include <__chrono/month_weekday.h> # include <__chrono/monthday.h> diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index 8820fb8c0936f96eef11fefac162bdd2133c77b0..1d12b6e8d86bba8c4f43f76ce8b25c7b2173d035 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -73,20 +73,6 @@ { include: [ "<__algorithm/pop_heap.h>", "private", "", "public" ] }, { include: [ "<__algorithm/prev_permutation.h>", "private", "", "public" ] }, { include: [ "<__algorithm/pstl_any_all_none_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backend.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backend.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/any_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/backend.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/fill.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/find_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/for_each.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/libdispatch.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/merge.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/serial.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/stable_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/thread.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/transform.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_backends/cpu_backends/transform_reduce.h>", "private", "", "public" ] }, { include: [ "<__algorithm/pstl_copy.h>", "private", "", "public" ] }, { include: [ "<__algorithm/pstl_count.h>", "private", "", "public" ] }, { include: [ "<__algorithm/pstl_equal.h>", "private", "", "public" ] }, @@ -281,6 +267,7 @@ { include: [ "<__chrono/high_resolution_clock.h>", "private", "", "public" ] }, { include: [ "<__chrono/leap_second.h>", "private", "", "public" ] }, { include: [ "<__chrono/literals.h>", "private", "", "public" ] }, + { include: [ "<__chrono/local_info.h>", "private", "", "public" ] }, { include: [ "<__chrono/month.h>", "private", "", "public" ] }, { include: [ "<__chrono/month_weekday.h>", "private", "", "public" ] }, { include: [ "<__chrono/monthday.h>", "private", "", "public" ] }, diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index ce133e471deb70e83a7e5aba9fdff5f1e6f1260b..64652c8307c9e6e69d83a11abae7383a3548aeab 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -714,32 +714,6 @@ module std_private_algorithm_partition_point [system module std_private_algorithm_pop_heap [system] { header "__algorithm/pop_heap.h" } module std_private_algorithm_prev_permutation [system] { header "__algorithm/prev_permutation.h" } module std_private_algorithm_pstl_any_all_none_of [system] { header "__algorithm/pstl_any_all_none_of.h" } -module std_private_algorithm_pstl_backend [system] { - header "__algorithm/pstl_backend.h" - export * -} -module std_private_algorithm_pstl_backends_cpu_backend [system] { - header "__algorithm/pstl_backends/cpu_backend.h" - export * -} -module std_private_algorithm_pstl_backends_cpu_backends_any_of [system] { header "__algorithm/pstl_backends/cpu_backends/any_of.h" } -module std_private_algorithm_pstl_backends_cpu_backends_backend [system] { - header "__algorithm/pstl_backends/cpu_backends/backend.h" - export * -} -module std_private_algorithm_pstl_backends_cpu_backends_fill [system] { header "__algorithm/pstl_backends/cpu_backends/fill.h" } -module std_private_algorithm_pstl_backends_cpu_backends_find_if [system] { header "__algorithm/pstl_backends/cpu_backends/find_if.h" } -module std_private_algorithm_pstl_backends_cpu_backends_for_each [system] { header "__algorithm/pstl_backends/cpu_backends/for_each.h" } -module std_private_algorithm_pstl_backends_cpu_backends_libdispatch [system] { header "__algorithm/pstl_backends/cpu_backends/libdispatch.h" } -module std_private_algorithm_pstl_backends_cpu_backends_merge [system] { header "__algorithm/pstl_backends/cpu_backends/merge.h" } -module std_private_algorithm_pstl_backends_cpu_backends_serial [system] { textual header "__algorithm/pstl_backends/cpu_backends/serial.h" } -module std_private_algorithm_pstl_backends_cpu_backends_stable_sort [system] { header "__algorithm/pstl_backends/cpu_backends/stable_sort.h" } -module std_private_algorithm_pstl_backends_cpu_backends_thread [system] { textual header "__algorithm/pstl_backends/cpu_backends/thread.h" } -module std_private_algorithm_pstl_backends_cpu_backends_transform [system] { - header "__algorithm/pstl_backends/cpu_backends/transform.h" - export std_private_algorithm_transform -} -module std_private_algorithm_pstl_backends_cpu_backends_transform_reduce [system] { header "__algorithm/pstl_backends/cpu_backends/transform_reduce.h" } module std_private_algorithm_pstl_copy [system] { header "__algorithm/pstl_copy.h" } module std_private_algorithm_pstl_count [system] { header "__algorithm/pstl_count.h" } module std_private_algorithm_pstl_equal [system] { header "__algorithm/pstl_equal.h" } @@ -1150,6 +1124,7 @@ module std_private_chrono_high_resolution_clock [system] { } module std_private_chrono_leap_second [system] { header "__chrono/leap_second.h" } module std_private_chrono_literals [system] { header "__chrono/literals.h" } +module std_private_chrono_local_info [system] { header "__chrono/local_info.h" } module std_private_chrono_month [system] { header "__chrono/month.h" } module std_private_chrono_month_weekday [system] { header "__chrono/month_weekday.h" } module std_private_chrono_monthday [system] { header "__chrono/monthday.h" } @@ -1613,7 +1588,26 @@ module std_private_numeric_transform_exclusive_scan [system] { header "__numeric module std_private_numeric_transform_inclusive_scan [system] { header "__numeric/transform_inclusive_scan.h" } module std_private_numeric_transform_reduce [system] { header "__numeric/transform_reduce.h" } -module std_private_pstl_cpu_algos_cpu_traits [system] { header "__pstl/cpu_algos/cpu_traits.h" } +module std_private_pstl_backends_libdispatch [system] { header "__pstl/backends/libdispatch.h" } +module std_private_pstl_backends_serial [system] { header "__pstl/backends/serial.h" } +module std_private_pstl_backends_std_thread [system] { header "__pstl/backends/std_thread.h" } +module std_private_pstl_cpu_algos_any_of [system] { textual header "__pstl/cpu_algos/any_of.h" } +module std_private_pstl_cpu_algos_cpu_traits [system] { header "__pstl/cpu_algos/cpu_traits.h" } +module std_private_pstl_cpu_algos_fill [system] { textual header "__pstl/cpu_algos/fill.h" } +module std_private_pstl_cpu_algos_find_if [system] { textual header "__pstl/cpu_algos/find_if.h" } +module std_private_pstl_cpu_algos_for_each [system] { textual header "__pstl/cpu_algos/for_each.h" } +module std_private_pstl_cpu_algos_merge [system] { textual header "__pstl/cpu_algos/merge.h" } +module std_private_pstl_cpu_algos_stable_sort [system] { textual header "__pstl/cpu_algos/stable_sort.h" } +module std_private_pstl_cpu_algos_transform [system] { textual header "__pstl/cpu_algos/transform.h" } +module std_private_pstl_cpu_algos_transform_reduce [system] { textual header "__pstl/cpu_algos/transform_reduce.h" } +module std_private_pstl_configuration_fwd [system] { + header "__pstl/configuration_fwd.h" + export * +} +module std_private_pstl_configuration [system] { + header "__pstl/configuration.h" + export * +} module std_private_queue_fwd [system] { header "__fwd/queue.h" } diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc index 575e6347aecce12cd2121630947ba3fb8f35a5d7..1265e21dc54ef66f5cb539a64bff30c2137d2167 100644 --- a/libcxx/modules/std/chrono.inc +++ b/libcxx/modules/std/chrono.inc @@ -215,6 +215,7 @@ export namespace std { # endif // if 0 // [time.zone.info], information classes + using std::chrono::local_info; using std::chrono::sys_info; # if 0 diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index a4a3fee8645710e75c3aff399fe6960eb4a2edc0..8b28d1b8918955d1f4ffb4e13f6b94e499bdb1db 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -327,7 +327,7 @@ set(LIBCXX_EXPERIMENTAL_SOURCES experimental/keep.cpp ) -if (LIBCXX_PSTL_CPU_BACKEND STREQUAL "libdispatch") +if (LIBCXX_PSTL_BACKEND STREQUAL "libdispatch") list(APPEND LIBCXX_EXPERIMENTAL_SOURCES pstl/libdispatch.cpp ) diff --git a/libcxx/src/pstl/libdispatch.cpp b/libcxx/src/pstl/libdispatch.cpp index d997a9c73463d3b67371e2659f98a32f22998fc9..3dca702341c85ad718ce3249de259f67747538b6 100644 --- a/libcxx/src/pstl/libdispatch.cpp +++ b/libcxx/src/pstl/libdispatch.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include <__algorithm/min.h> -#include <__algorithm/pstl_backends/cpu_backends/libdispatch.h> #include <__config> +#include <__pstl/backends/libdispatch.h> #include _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/libcxx/test/libcxx/algorithms/pstl.libdispatch.chunk_partitions.pass.cpp b/libcxx/test/libcxx/algorithms/pstl.libdispatch.chunk_partitions.pass.cpp index 8c7016a80b811ae1e4e6e30e8242ec55e51c2a08..b48ac02dd79c59b86c726fb24ff46a0a7b3c1338 100644 --- a/libcxx/test/libcxx/algorithms/pstl.libdispatch.chunk_partitions.pass.cpp +++ b/libcxx/test/libcxx/algorithms/pstl.libdispatch.chunk_partitions.pass.cpp @@ -8,11 +8,11 @@ // -// REQUIRES: libcpp-pstl-cpu-backend-libdispatch +// REQUIRES: libcpp-pstl-backend-libdispatch // __chunk_partitions __partition_chunks(ptrdiff_t); -#include <__algorithm/pstl_backends/cpu_backends/libdispatch.h> +#include <__pstl/backends/libdispatch.h> #include #include diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d18076a642ec6ac376bb1574ff456eaaf31c2c85 --- /dev/null +++ b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-localization + +// TODO FMT This test should not require std::to_chars(floating-point) +// XFAIL: availability-fp_to_chars-missing + +// XFAIL: libcpp-has-no-incomplete-tzdb + +// + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const local_info& r); + +// [time.zone.info.local] +// 7 Effects: Streams out the local_info object r in an unspecified format. +// 8 Returns: os. +// +// Tests the output produced by this function. + +#include +#include +#include +#include + +#include "assert_macros.h" +#include "test_macros.h" +#include "make_string.h" +#include "concat_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test(std::basic_string_view expected, std::chrono::local_info&& info) { + std::basic_stringstream sstr; + sstr << info; + std::basic_string output = sstr.str(); + + TEST_REQUIRE(expected == output, + TEST_WRITE_CONCATENATED("\nExpected output ", expected, "\nActual output ", output, '\n')); +} + +template +static void test() { + using namespace std::literals::chrono_literals; + namespace tz = std::chrono; + // result values matching the "known" results + test(SV("unique: " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + tz::local_info{tz::local_info::unique, + tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, + tz::sys_info{}}); + + test(SV("non-existent: " + "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"NEG\", " + "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min \"POS\"}"), + tz::local_info{ + tz::local_info::nonexistent, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "NEG"}, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + -(12h + 23min + 45s), + 67min, + "POS"}}); + + test(SV("ambiguous: " + "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"NEG\", " + "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min \"POS\"}"), + tz::local_info{ + tz::local_info::ambiguous, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "NEG"}, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + -(12h + 23min + 45s), + 67min, + "POS"}}); + + // result values not matching the "known" results + test( + SV("unspecified result (-1): " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + tz::local_info{-1, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}}); + test(SV("unspecified result (3): " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + tz::local_info{3, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}}); +} + +int main(int, const char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..faa7d855c8de7d6fdf0a1f8611f7e8e1438d103a --- /dev/null +++ b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-localization + +// TODO FMT This test should not require std::to_chars(floating-point) +// XFAIL: availability-fp_to_chars-missing + +// XFAIL: libcpp-has-no-incomplete-tzdb + +// + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const sys_info& r); + +// [time.zone.info.sys] +// 7 Effects: Streams out the sys_info object r in an unspecified format. +// 8 Returns: os. +// +// Tests the output produced by this function. + +#include +#include +#include +#include + +#include "assert_macros.h" +#include "test_macros.h" +#include "make_string.h" +#include "concat_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test(std::basic_string_view expected, std::chrono::sys_info&& info) { + std::basic_stringstream sstr; + sstr << info; + std::basic_string output = sstr.str(); + + TEST_REQUIRE(expected == output, + TEST_WRITE_CONCATENATED("\nExpected output ", expected, "\nActual output ", output, '\n')); +} + +template +static void test() { + using namespace std::literals::chrono_literals; + namespace tz = std::chrono; + + test(SV("[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\""), + tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}); + + test(SV("[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"DMY\""), + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "DMY"}); +} + +int main(int, const char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/libcxx/vendor/apple/system-install-properties.sh.cpp b/libcxx/test/libcxx/vendor/apple/system-install-properties.sh.cpp index 3e2e080368f4c2c058bfca315bbe8693eb47ee66..4ea27401e35d4d033666a8790230048975ad6f27 100644 --- a/libcxx/test/libcxx/vendor/apple/system-install-properties.sh.cpp +++ b/libcxx/test/libcxx/vendor/apple/system-install-properties.sh.cpp @@ -45,4 +45,4 @@ // Make sure we use the libdispatch backend for the PSTL. // -// RUN: grep "%{include-dir}/__config_site" -e '#define _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH' +// RUN: grep "%{include-dir}/__config_site" -e '#define _LIBCPP_PSTL_BACKEND_LIBDISPATCH' diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp index 16df3e40bd77a000b643c4127e3ee72301cd7c2f..4dd52a80a0ebada52208c44f9ae0075ea57d5247 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp @@ -27,6 +27,7 @@ #include #include "test_iterators.h" +#include "test_range.h" constexpr void compareOperatorTest(const auto& iter1, const auto& iter2) { assert(!(iter1 < iter1)); @@ -139,8 +140,7 @@ constexpr bool test() { auto it = ev.begin(); using ElemIter = decltype(it); - static_assert(!std::invocable, ElemIter, ElemIter>); - static_assert(!std::invocable, ElemIter, ElemIter>); + static_assert(!weakly_equality_comparable_with); inequalityOperatorsDoNotExistTest(it, it); } diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp index df95e07c97d972f78095bfab51f713d648611579..d8a3149398bf757b4791badf791d94f9aa048909 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp @@ -17,6 +17,7 @@ #include #include "../types.h" +#include "test_range.h" template struct Iter { @@ -63,37 +64,33 @@ struct Range : TupleBufferView { using R = Range; using CrossComparableR = Range; -// Test Constraint -template -concept HasEqual = requires(const I i, const S s) { i == s; }; - using std::ranges::elements_view; using std::ranges::iterator_t; using std::ranges::sentinel_t; -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(!HasEqual>, // - sentinel_t>>); +static_assert(!weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(!HasEqual>, // - sentinel_t>>); +static_assert(!weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); template constexpr void testOne() { diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp index 78881e8ac6df1947429ffe11d4cf66ca94661e17..11cba3c1ba308068f12fc697513d37d799ee63fa 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp @@ -17,12 +17,12 @@ #include #include #include + #include "test_iterators.h" #include "test_macros.h" -#include "../types.h" +#include "test_range.h" -template -concept has_equal = requires (T const& x, T const& y) { { x == y }; }; +#include "../types.h" template constexpr void test() { @@ -76,7 +76,7 @@ constexpr bool tests() { using Sentinel = sentinel_wrapper; using FilterView = std::ranges::filter_view, AlwaysTrue>; using FilterIterator = std::ranges::iterator_t; - static_assert(!has_equal); + static_assert(!weakly_equality_comparable_with); } return true; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/eq.pass.cpp index bc7d4bec94d3e63a753c073e00fb4fda47011b7b..9d6cb76902622968f25d73b47222d59befe8b18e 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/eq.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/eq.pass.cpp @@ -19,9 +19,7 @@ #include #include "../types.h" - -template -concept EqualityComparable = std::invocable, const Iter&, const Sent&> ; +#include "test_range.h" using Iterator = random_access_iterator*>; using ConstIterator = random_access_iterator*>; @@ -53,10 +51,10 @@ struct ConstComparableView : BufferView*> { constexpr auto end() const { return ConstComparableSentinel(ConstIterator(data_ + size_)); } }; -static_assert(EqualityComparable, - std::ranges::sentinel_t>); -static_assert(EqualityComparable, - std::ranges::sentinel_t>); +static_assert(weakly_equality_comparable_with, + std::ranges::sentinel_t>); +static_assert(weakly_equality_comparable_with, + std::ranges::sentinel_t>); constexpr bool test() { int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/equal.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/equal.pass.cpp index 5a83a05ead919825c9d9d2c0c2ac88935b4a0048..dbf3bfa126ae8a2a5dfd5e53be62852793bf69ee 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/equal.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/equal.pass.cpp @@ -17,13 +17,10 @@ #include #include + #include "../types.h" -template -concept CanCallEquals = requires(const Iter& i) { - i == i; - i != i; -}; +#include "test_range.h" constexpr bool test() { // When `View` is a forward range, `inner-iterator` supports both overloads of `operator==`. @@ -56,7 +53,7 @@ constexpr bool test() { auto b = val.begin(); std::same_as decltype(auto) e = val.end(); - static_assert(!CanCallEquals); + static_assert(!weakly_equality_comparable_with); assert(!(b == std::default_sentinel)); assert(b != std::default_sentinel); diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/equal.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/equal.pass.cpp index 49cac708947325e7d459395a4f8466549aa6e553..6cbc98a94645f556d21aaf9c53a3ea6366cdf286 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/equal.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/equal.pass.cpp @@ -17,13 +17,10 @@ #include #include + #include "../types.h" -template -concept CanCallEquals = requires(const Iter& i) { - i == i; - i != i; -}; +#include "test_range.h" constexpr bool test() { // Forward range supports both overloads of `operator==`. @@ -69,7 +66,7 @@ constexpr bool test() { auto b = v.begin(); std::same_as decltype(auto) e = v.end(); - static_assert(!CanCallEquals); + static_assert(!weakly_equality_comparable_with); assert(!(b == std::default_sentinel)); assert(b != std::default_sentinel); diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/equality.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/equality.pass.cpp index db3e5764421af7b1faff4b06ac27f592a5c3ca1d..b00b3dd0bd053ca2e65e19e455c3fd2924a80249 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/equality.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/equality.pass.cpp @@ -70,37 +70,33 @@ struct LessThan3 { constexpr bool operator()(int i) const { return i < 3; } }; -// Test Constraint -template -concept HasEqual = requires(const I i, const S s) { i == s; }; - using std::ranges::iterator_t; using std::ranges::sentinel_t; using std::ranges::take_while_view; -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(!HasEqual>, // - sentinel_t>>); +static_assert(!weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(!HasEqual>, // - sentinel_t>>); +static_assert(!weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); -static_assert(HasEqual>, // - sentinel_t>>); +static_assert(weakly_equality_comparable_with>, // + sentinel_t>>); template constexpr void testOne() { diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp index 1873481d73225357cd3e3f3a1c6a997633ea19a5..9f11a991535e771ee1da054a0b844186a3a18b1f 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp @@ -11,8 +11,9 @@ // constexpr auto begin() requires (!simple-view); // constexpr auto begin() const requires range; -#include #include +#include +#include #include "test_macros.h" #include "test_iterators.h" @@ -27,55 +28,104 @@ struct NonCommonSimpleView : std::ranges::view_base { static_assert(std::ranges::sized_range); static_assert(!std::ranges::sized_range); +using CommonInputIterPtrConstInt = common_input_iterator; +using CountedCommonInputIterPtrConstInt = std::counted_iterator; + constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - // sized_range && random_access_iterator + // simple-view && sized_range && random_access_range { - std::ranges::take_view tv(SizedRandomAccessView(buffer), 4); - assert(tv.begin() == SizedRandomAccessView(buffer).begin()); - ASSERT_SAME_TYPE(decltype(tv.begin()), RandomAccessIter); - } + using ViewTested = SizedRandomAccessView; + static_assert(simple_view); + static_assert(std::ranges::sized_range); + static_assert(std::ranges::random_access_range); - { - const std::ranges::take_view tv(SizedRandomAccessView(buffer), 4); - assert(tv.begin() == SizedRandomAccessView(buffer).begin()); + std::ranges::take_view tv(ViewTested(buffer), 4); + assert(tv.begin() == ViewTested(buffer).begin()); ASSERT_SAME_TYPE(decltype(tv.begin()), RandomAccessIter); - } - // sized_range && !random_access_iterator - { - std::ranges::take_view tv(SizedForwardView{buffer}, 4); - assert(tv.begin() == std::counted_iterator(ForwardIter(buffer), 4)); - ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator); + const std::ranges::take_view ctv(ViewTested(buffer), 4); + assert(ctv.begin() == ViewTested(buffer).begin()); + ASSERT_SAME_TYPE(decltype(ctv.begin()), RandomAccessIter); } + // simple-view && sized_range && !random_access_range { - const std::ranges::take_view tv(SizedForwardView{buffer}, 4); - assert(tv.begin() == std::counted_iterator(ForwardIter(buffer), 4)); + using ViewTested = SizedForwardView; + static_assert(simple_view); + static_assert(std::ranges::sized_range); + static_assert(!std::ranges::random_access_range); + + std::ranges::take_view tv(ViewTested{buffer}, 16); // underlying size is 8 + assert(tv.begin() == std::counted_iterator(ForwardIter(buffer), 8)); // expect min(8, 16) ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator); + + const std::ranges::take_view ctv(ViewTested{buffer}, 4); + assert(ctv.begin() == std::counted_iterator(ForwardIter(buffer), 4)); + ASSERT_SAME_TYPE(decltype(ctv.begin()), std::counted_iterator); } - // !sized_range + // simple-view && !sized_range { - std::ranges::take_view tv(MoveOnlyView{buffer}, 4); + using ViewTested = MoveOnlyView; + static_assert(simple_view); + std::ranges::take_view tv(ViewTested{buffer}, 4); assert(tv.begin() == std::counted_iterator(buffer, 4)); ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator); + + const std::ranges::take_view ctv(ViewTested{buffer}, 4); + assert(ctv.begin() == std::counted_iterator(buffer, 4)); + ASSERT_SAME_TYPE(decltype(ctv.begin()), std::counted_iterator); } + // simple-view && sized_range && !sized_range { - const std::ranges::take_view tv(MoveOnlyView{buffer}, 4); - assert(tv.begin() == std::counted_iterator(buffer, 4)); + using ViewTested = NonCommonSimpleView; + static_assert(simple_view); + static_assert(std::ranges::sized_range); + static_assert(!std::ranges::sized_range); + + std::ranges::take_view tv{}; ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator); + ASSERT_SAME_TYPE(decltype(std::as_const(tv).begin()), std::counted_iterator); } - // simple-view && sized_range && !size_range + // !simple-view && !sized_range { - std::ranges::take_view tv{}; - ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator); - ASSERT_SAME_TYPE(decltype(std::as_const(tv).begin()), std::counted_iterator); + using ViewTested = NonSimpleNonSizedView; + static_assert(!simple_view); + static_assert(!std::ranges::sized_range); + + std::ranges::take_view tv{ViewTested{buffer, buffer + 2}, 4}; + // The count for the counted iterator is the count of the take_view (i.e., 4) + assert(tv.begin() == CountedCommonInputIterPtrConstInt(CommonInputIterPtrConstInt(buffer), 4)); + ASSERT_SAME_TYPE(decltype(tv.begin()), CountedCommonInputIterPtrConstInt); } + // !simple-view && sized_range + { + using ViewTested = NonSimpleSizedView; + static_assert(!simple_view); + static_assert(std::ranges::sized_range); + + std::ranges::take_view tv{ViewTested{buffer, buffer + 2}, 4}; + // The count for the counted iterator is the min(2, 4) (i.e., 2). + assert(tv.begin() == CountedCommonInputIterPtrConstInt(CommonInputIterPtrConstInt(buffer), 2)); + ASSERT_SAME_TYPE(decltype(tv.begin()), CountedCommonInputIterPtrConstInt); + } + + // !simple-view && sized_range && random_access_range + { + using ViewTested = NonSimpleSizedRandomView; + static_assert(!simple_view); + static_assert(std::ranges::sized_range); + static_assert(std::ranges::random_access_range); + + std::ranges::take_view tv{ViewTested{buffer, buffer + 2}, 4}; + assert(tv.begin() == random_access_iterator(buffer)); + ASSERT_SAME_TYPE(decltype(tv.begin()), random_access_iterator); + } return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/end.pass.cpp index 6cab05daa9e059ac56c383df0a22398e50695081..eddb39af2712145bb418815d18b418883a1ffa04 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.take/end.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/end.pass.cpp @@ -69,6 +69,20 @@ constexpr bool test() { assert(tv.end() == std::ranges::next(tv.begin(), 8)); } + { + // __iterator has base with type std::ranges::sentinel_t; adding a const qualifier + // would change the equality. + std::ranges::take_view tvns(NonSimpleNonSizedView{buffer, buffer + 8}, 0); + static_assert(!std::is_same_v>); + } + + { + // __iterator has base with type std::ranges::sentinel_t; adding a const qualifier + // would not change the equality. + std::ranges::take_view tvs(SimpleViewNonSized{buffer, buffer + 8}, 0); + static_assert(std::is_same_v>); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/eq.pass.cpp index e6f433e30f60db2128abea66ea75f00564c2b85c..1e4d2a4dccfa4506a169967a0b220c3d92facf6b 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/eq.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/eq.pass.cpp @@ -21,6 +21,7 @@ #include "test_comparisons.h" #include "test_iterators.h" +#include "test_range.h" template using MaybeConstIterator = cpp20_input_iterator>; @@ -77,14 +78,6 @@ struct NonCrossConstComparableView : std::ranges::view_base { static_assert(std::ranges::range); static_assert(std::ranges::range); -template -concept weakly_equality_comparable_with = requires(const T& t, const U& u) { - t == u; - t != u; - u == t; - u != t; -}; - constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; using CrossConstComparableTakeView = std::ranges::take_view; diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/types.h b/libcxx/test/std/ranges/range.adaptors/range.take/types.h index db80e68bb21afef163014b5ade6fe4e03fd62215..7590ce33bffc1047440daf06836d8f651a8c9d15 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.take/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.take/types.h @@ -65,4 +65,54 @@ private: int* end_; }; +template