diff --git a/buildbot/dependency.conf b/buildbot/dependency.conf index 48847132b0642..33f57844515f0 100644 --- a/buildbot/dependency.conf +++ b/buildbot/dependency.conf @@ -1,8 +1,8 @@ [VERSIONS] -# https://github.com/intel/llvm/releases/download/2020-WW41/oclcpuexp-2020.11.10.0.05_rel.tar.gz -ocl_cpu_rt_ver=2020.11.10.0.05 -# https://github.com/intel/llvm/releases/download/2020-WW41/win-oclcpuexp-2020.11.10.0.05_rel.zip -ocl_cpu_rt_ver_win=2020.11.10.0.05 +# https://github.com/intel/llvm/releases/download/2020-WW45/oclcpuexp-2020.11.11.0.04_rel.tar.gz +ocl_cpu_rt_ver=2020.11.11.0.04 +# https://github.com/intel/llvm/releases/download/2020-WW45/win-oclcpuexp-2020.11.11.0.04_rel.zip +ocl_cpu_rt_ver_win=2020.11.11.0.04 # Same GPU driver supports Level Zero and OpenCL: # https://github.com/intel/compute-runtime/releases/tag/20.42.18209 ocl_gpu_rt_ver=20.42.18209 @@ -10,24 +10,24 @@ ocl_gpu_rt_ver=20.42.18209 # https://downloadmirror.intel.com/29879/a08/igfx_win10_100.8778.zip ocl_gpu_rt_ver_win=27.20.100.8778 intel_sycl_ver=build -# https://github.com/oneapi-src/oneTBB/releases/download/v2021.1-beta08/oneapi-tbb-2021.1-beta08-lin.tgz -tbb_ver=2021.1.10.2267 -# https://github.com/oneapi-src/oneTBB/releases/download/v2021.1-beta08/oneapi-tbb-2021.1-beta08-win.zip -tbb_ver_win=2021.1.10.2267 -# https://github.com/intel/llvm/releases/download/2020-WW41/fpgaemu-2020.11.10.0.05_rel.tar.gz -ocl_fpga_emu_ver=2020.11.10.0.05 -# https://github.com/intel/llvm/releases/download/2020-WW41/win-fpgaemu-2020.11.10.0.05_rel.zip -ocl_fpga_emu_ver_win=2020.11.10.0.05 -fpga_ver=20200913_000017 -fpga_ver_win=20200913_000017 +# https://github.com/oneapi-src/oneTBB/releases/download/v2021.1-beta10/oneapi-tbb-2021.1-beta10-lin.tgz +tbb_ver=2021.1.053 +# https://github.com/oneapi-src/oneTBB/releases/download/v2021.1-beta10/oneapi-tbb-2021.1-beta10-win.zip +tbb_ver_win=2021.1.049 +# https://github.com/intel/llvm/releases/download/2020-WW45/fpgaemu-2020.11.11.0.04_rel.tar.gz +ocl_fpga_emu_ver=2020.11.11.0.04 +# https://github.com/intel/llvm/releases/download/2020-WW45/win-fpgaemu-2020.11.11.0.04_rel.zip +ocl_fpga_emu_ver_win=2020.11.11.0.04 +fpga_ver=20201021_000005 +fpga_ver_win=20201022_000005 [DRIVER VERSIONS] -cpu_driver_lin=2020.11.10.0.05 -cpu_driver_win=2020.11.10.0.05 +cpu_driver_lin=2020.11.11.0.04 +cpu_driver_win=2020.11.11.0.04 gpu_driver_lin=20.42.18209 gpu_driver_win=27.20.100.8778 -fpga_driver_lin=2020.11.10.0.05 -fpga_driver_win=2020.11.10.0.05 +fpga_driver_lin=2020.11.11.0.04 +fpga_driver_win=2020.11.11.0.04 # NVidia CUDA driver # TODO provide URL for CUDA driver nvidia_gpu_driver_lin=435.21 diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index f20182bd25e64..9e693b62e50d8 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -13,13 +13,22 @@ #include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/ASTReader.h" +#define DEBUG_TYPE "clang-tidy" + namespace clang { namespace tooling { class ExpandModularHeadersPPCallbacks::FileRecorder { public: /// Records that a given file entry is needed for replaying callbacks. - void addNecessaryFile(const FileEntry *File) { FilesToRecord.insert(File); } + void addNecessaryFile(const FileEntry *File) { + // Don't record modulemap files because it breaks same file detection. + if (!(File->getName().endswith("module.modulemap") || + File->getName().endswith("module.private.modulemap") || + File->getName().endswith("module.map") || + File->getName().endswith("module_private.map"))) + FilesToRecord.insert(File); + } /// Records content for a file and adds it to the FileSystem. void recordFileContent(const FileEntry *File, @@ -30,12 +39,12 @@ class ExpandModularHeadersPPCallbacks::FileRecorder { return; // FIXME: Why is this happening? We might be losing contents here. - if (!ContentCache.getRawBuffer()) + llvm::Optional Data = ContentCache.getBufferDataIfLoaded(); + if (!Data) return; InMemoryFs.addFile(File->getName(), /*ModificationTime=*/0, - llvm::MemoryBuffer::getMemBufferCopy( - ContentCache.getRawBuffer()->getBuffer())); + llvm::MemoryBuffer::getMemBufferCopy(*Data)); // Remove the file from the set of necessary files. FilesToRecord.erase(File); } @@ -44,8 +53,8 @@ class ExpandModularHeadersPPCallbacks::FileRecorder { /// `FilesToRecord` should be empty. void checkAllFilesRecorded() { for (auto FileEntry : FilesToRecord) - llvm::errs() << "Did not record contents for input file: " - << FileEntry->getName() << "\n"; + LLVM_DEBUG(llvm::dbgs() << "Did not record contents for input file: " + << FileEntry->getName() << "\n"); } private: diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h index 72f96d0945625..075b5f0ce450a 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h +++ b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h @@ -25,6 +25,9 @@ namespace readability { /// This check is similar to `-Wold-style-cast`, but it suggests automated fixes /// in some cases. The reported locations should not be different from the /// ones generated by `-Wold-style-cast`. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-casting.html class AvoidCStyleCastsCheck : public ClangTidyCheck { public: AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h index 6a690f60da1c2..a9989ee51bcf6 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h +++ b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h @@ -18,6 +18,9 @@ namespace readability { // Check for underscores in the names of googletest tests, per // https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.html class AvoidUnderscoreInGoogletestNameCheck : public ClangTidyCheck { public: using ClangTidyCheck::ClangTidyCheck; diff --git a/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h b/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h index 574965dc556a6..089d463ff9852 100644 --- a/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h +++ b/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h @@ -18,6 +18,9 @@ namespace google { /// Checks that default parameters are not given for virtual methods. /// /// See https://google.github.io/styleguide/cppguide.html#Default_Arguments +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-default-arguments.html class DefaultArgumentsCheck : public ClangTidyCheck { public: DefaultArgumentsCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h index 721ad4efc9797..573b0e18f90db 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h +++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h @@ -18,6 +18,9 @@ namespace google { /// Checks that all single-argument constructors are explicit. /// /// See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-explicit-constructor.html class ExplicitConstructorCheck : public ClangTidyCheck { public: ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h b/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h index dae66c8afa8b9..56ca5b20966e1 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h +++ b/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h @@ -22,6 +22,9 @@ namespace build { /// specified explicitly, and such use isn't intended in any case. /// /// Corresponding cpplint.py check name: 'build/explicit_make_pair'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-build-explicit-make-pair.html class ExplicitMakePairCheck : public ClangTidyCheck { public: ExplicitMakePairCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h index aa569dedcdb4b..801d362aa5094 100644 --- a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h +++ b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h @@ -27,6 +27,9 @@ namespace readability { /// /// For extension-less header files, using an empty string or leaving an /// empty string between ";" if there are other filename extensions. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-global-names-in-headers.html class GlobalNamesInHeadersCheck : public ClangTidyCheck { public: GlobalNamesInHeadersCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h index 0b528dab2476d..5b2d2f501c91a 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h @@ -25,6 +25,9 @@ namespace runtime { /// with `u?intXX(_t)?`. /// /// Corresponding cpplint.py check: 'runtime/int'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-runtime-int.html class IntegerTypesCheck : public ClangTidyCheck { public: IntegerTypesCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h b/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h index 33cf4d62a45a6..7f513387ed616 100644 --- a/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h +++ b/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h @@ -21,6 +21,9 @@ namespace runtime { /// https://google.github.io/styleguide/cppguide.html#Operator_Overloading /// /// Corresponding cpplint.py check name: 'runtime/operator'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-runtime-operator.html class OverloadedUnaryAndCheck : public ClangTidyCheck { public: OverloadedUnaryAndCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h index 8c32dddc28373..ee14997f1506d 100644 --- a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h +++ b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h @@ -19,6 +19,9 @@ namespace readability { /// Finds TODO comments without a username or bug number. /// /// Corresponding cpplint.py check: 'readability/todo' +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-todo.html class TodoCommentCheck : public ClangTidyCheck { public: TodoCommentCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h index 52af823e6a0e1..22110215a5efe 100644 --- a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h +++ b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h @@ -30,6 +30,9 @@ namespace build { /// https://google.github.io/styleguide/cppguide.html#Namespaces /// /// Corresponding cpplint.py check name: 'build/namespaces'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-build-namespaces.html class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck { public: UnnamedNamespaceInHeaderCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h b/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h index 97a1afbf160fe..c1b86c953fc59 100644 --- a/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h +++ b/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h @@ -31,6 +31,9 @@ namespace build { /// \endcode /// /// Corresponding cpplint.py check name: `build/namespaces`. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/google-build-using-namespace.html class UsingNamespaceDirectiveCheck : public ClangTidyCheck { public: UsingNamespaceDirectiveCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 03b4450d8ca8c..24847d80657c1 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -63,8 +63,10 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { declStmt( has(varDecl(hasLocalStorage(), hasType(qualType( - hasCanonicalType( - matchers::isExpensiveToCopy()), + hasCanonicalType(allOf( + matchers::isExpensiveToCopy(), + unless(hasDeclaration(namedDecl( + hasName("::std::function")))))), unless(hasDeclaration(namedDecl( matchers::matchesAnyListedName( AllowedTypes)))))), diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index c8096017b50ab..6ca9c4f93d16e 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -170,10 +170,9 @@ class ReplayPreamble : private PPCallbacks { void replay() { for (const auto &Inc : Includes) { - const FileEntry *File = nullptr; + llvm::Optional File; if (Inc.Resolved != "") - if (auto FE = SM.getFileManager().getFile(Inc.Resolved)) - File = *FE; + File = expectedToOptional(SM.getFileManager().getFileRef(Inc.Resolved)); // Re-lex the #include directive to find its interesting parts. auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset); @@ -211,17 +210,16 @@ class ReplayPreamble : private PPCallbacks { SynthesizedFilenameTok.setKind(tok::header_name); SynthesizedFilenameTok.setLiteralData(Inc.Written.data()); + const FileEntry *FE = File ? &File->getFileEntry() : nullptr; llvm::StringRef WrittenFilename = llvm::StringRef(Inc.Written).drop_front().drop_back(); Delegate->InclusionDirective(HashTok->location(), SynthesizedIncludeTok, WrittenFilename, Inc.Written.front() == '<', - FileTok->range(SM).toCharRange(SM), File, + FileTok->range(SM).toCharRange(SM), FE, "SearchPath", "RelPath", /*Imported=*/nullptr, Inc.FileKind); if (File) - // FIXME: Use correctly named FileEntryRef. - Delegate->FileSkipped(FileEntryRef(File->getName(), *File), - SynthesizedFilenameTok, Inc.FileKind); + Delegate->FileSkipped(*File, SynthesizedFilenameTok, Inc.FileKind); else { llvm::SmallString<1> UnusedRecovery; Delegate->FileNotFound(WrittenFilename, UnusedRecovery); diff --git a/clang-tools-extra/clangd/index/remote/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/CMakeLists.txt index 81287b58afa52..e3782d9701c74 100644 --- a/clang-tools-extra/clangd/index/remote/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/remote/CMakeLists.txt @@ -1,5 +1,7 @@ if (CLANGD_ENABLE_REMOTE) - generate_grpc_protos(RemoteIndexProtos "Index.proto") + generate_protos(RemoteIndexServiceProto "Service.proto" GRPC) + generate_protos(RemoteIndexProto "Index.proto") + add_dependencies(RemoteIndexServiceProto RemoteIndexProto) include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../) @@ -12,7 +14,8 @@ if (CLANGD_ENABLE_REMOTE) Client.cpp LINK_LIBS - RemoteIndexProtos + RemoteIndexProto + RemoteIndexServiceProto clangdRemoteMarshalling protobuf @@ -21,7 +24,8 @@ if (CLANGD_ENABLE_REMOTE) clangdSupport DEPENDS - RemoteIndexProtos + RemoteIndexProto + RemoteIndexServiceProto ) add_subdirectory(marshalling) diff --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp index 131e4c0b2fce2..a134d9c72932d 100644 --- a/clang-tools-extra/clangd/index/remote/Client.cpp +++ b/clang-tools-extra/clangd/index/remote/Client.cpp @@ -9,12 +9,13 @@ #include #include "Client.h" -#include "Index.grpc.pb.h" +#include "Service.grpc.pb.h" #include "index/Index.h" #include "index/Serialization.h" #include "marshalling/Marshalling.h" #include "support/Logger.h" #include "support/Trace.h" +#include "clang/Basic/Version.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -28,7 +29,8 @@ namespace { class IndexClient : public clangd::SymbolIndex { template using StreamingCall = std::unique_ptr> ( - remote::SymbolIndex::Stub::*)(grpc::ClientContext *, const RequestT &); + remote::v1::SymbolIndex::Stub::*)(grpc::ClientContext *, + const RequestT &); template @@ -40,6 +42,7 @@ class IndexClient : public clangd::SymbolIndex { const auto RPCRequest = ProtobufMarshaller->toProtobuf(Request); SPAN_ATTACH(Tracer, "Request", RPCRequest.DebugString()); grpc::ClientContext Context; + Context.AddMetadata("version", clang::getClangToolFullVersion("clangd")); std::chrono::system_clock::time_point Deadline = std::chrono::system_clock::now() + DeadlineWaitingTime; Context.set_deadline(Deadline); @@ -73,7 +76,7 @@ class IndexClient : public clangd::SymbolIndex { IndexClient( std::shared_ptr Channel, llvm::StringRef ProjectRoot, std::chrono::milliseconds DeadlineTime = std::chrono::milliseconds(1000)) - : Stub(remote::SymbolIndex::NewStub(Channel)), + : Stub(remote::v1::SymbolIndex::NewStub(Channel)), ProtobufMarshaller(new Marshaller(/*RemoteIndexRoot=*/"", /*LocalIndexRoot=*/ProjectRoot)), DeadlineWaitingTime(DeadlineTime) { @@ -82,25 +85,26 @@ class IndexClient : public clangd::SymbolIndex { void lookup(const clangd::LookupRequest &Request, llvm::function_ref Callback) const { - streamRPC(Request, &remote::SymbolIndex::Stub::Lookup, Callback); + streamRPC(Request, &remote::v1::SymbolIndex::Stub::Lookup, Callback); } bool fuzzyFind(const clangd::FuzzyFindRequest &Request, llvm::function_ref Callback) const { - return streamRPC(Request, &remote::SymbolIndex::Stub::FuzzyFind, Callback); + return streamRPC(Request, &remote::v1::SymbolIndex::Stub::FuzzyFind, + Callback); } bool refs(const clangd::RefsRequest &Request, llvm::function_ref Callback) const { - return streamRPC(Request, &remote::SymbolIndex::Stub::Refs, Callback); + return streamRPC(Request, &remote::v1::SymbolIndex::Stub::Refs, Callback); } void relations(const clangd::RelationsRequest &Request, llvm::function_ref Callback) const { - streamRPC(Request, &remote::SymbolIndex::Stub::Relations, + streamRPC(Request, &remote::v1::SymbolIndex::Stub::Relations, // Unpack protobuf Relation. [&](std::pair SubjectAndObject) { Callback(SubjectAndObject.first, SubjectAndObject.second); @@ -112,7 +116,7 @@ class IndexClient : public clangd::SymbolIndex { size_t estimateMemoryUsage() const { return 0; } private: - std::unique_ptr Stub; + std::unique_ptr Stub; std::unique_ptr ProtobufMarshaller; // Each request will be terminated if it takes too long. std::chrono::milliseconds DeadlineWaitingTime; diff --git a/clang-tools-extra/clangd/index/remote/Index.proto b/clang-tools-extra/clangd/index/remote/Index.proto index 305164ffef779..7619d0cb2ef3a 100644 --- a/clang-tools-extra/clangd/index/remote/Index.proto +++ b/clang-tools-extra/clangd/index/remote/Index.proto @@ -6,22 +6,10 @@ // //===----------------------------------------------------------------------===// -syntax = "proto3"; +syntax = "proto2"; package clang.clangd.remote; -// Semantics of SymbolIndex match clangd::SymbolIndex with all required -// structures corresponding to their clangd::* counterparts. -service SymbolIndex { - rpc Lookup(LookupRequest) returns (stream LookupReply) {} - - rpc FuzzyFind(FuzzyFindRequest) returns (stream FuzzyFindReply) {} - - rpc Refs(RefsRequest) returns (stream RefsReply) {} - - rpc Relations(RelationsRequest) returns (stream RelationsReply) {} -} - message LookupRequest { repeated string ids = 1; } // The response is a stream of symbol messages and the terminating message @@ -34,11 +22,11 @@ message LookupReply { } message FuzzyFindRequest { - string query = 1; + optional string query = 1; repeated string scopes = 2; - bool any_scope = 3; - uint32 limit = 4; - bool restricted_for_code_completion = 5; + optional bool any_scope = 3; + optional uint32 limit = 4; + optional bool restricted_for_code_completion = 5; repeated string proximity_paths = 6; repeated string preferred_types = 7; } @@ -54,8 +42,8 @@ message FuzzyFindReply { message RefsRequest { repeated string ids = 1; - uint32 filter = 2; - uint32 limit = 3; + optional uint32 filter = 2; + optional uint32 limit = 3; } // The response is a stream of reference messages, and one terminating has_more @@ -68,59 +56,59 @@ message RefsReply { } message Symbol { - string id = 1; - SymbolInfo info = 2; - string name = 3; - SymbolLocation definition = 4; - string scope = 5; - SymbolLocation canonical_declaration = 6; - int32 references = 7; - uint32 origin = 8; - string signature = 9; - string template_specialization_args = 10; - string completion_snippet_suffix = 11; - string documentation = 12; - string return_type = 13; - string type = 14; + optional string id = 1; + optional SymbolInfo info = 2; + optional string name = 3; + optional SymbolLocation definition = 4; + optional string scope = 5; + optional SymbolLocation canonical_declaration = 6; + optional int32 references = 7; + optional uint32 origin = 8; + optional string signature = 9; + optional string template_specialization_args = 10; + optional string completion_snippet_suffix = 11; + optional string documentation = 12; + optional string return_type = 13; + optional string type = 14; repeated HeaderWithReferences headers = 15; - uint32 flags = 16; + optional uint32 flags = 16; } message Ref { - SymbolLocation location = 1; - uint32 kind = 2; + optional SymbolLocation location = 1; + optional uint32 kind = 2; } message SymbolInfo { - uint32 kind = 1; - uint32 subkind = 2; - uint32 language = 3; - uint32 properties = 4; + optional uint32 kind = 1; + optional uint32 subkind = 2; + optional uint32 language = 3; + optional uint32 properties = 4; } message SymbolLocation { - Position start = 1; - Position end = 2; + optional Position start = 1; + optional Position end = 2; // clangd::SymbolLocation stores FileURI, but the protocol transmits a the // relative path. Because paths are different on the remote and local machines // they will be translated in the marshalling layer. - string file_path = 3; + optional string file_path = 3; } message Position { - uint32 line = 1; - uint32 column = 2; + optional uint32 line = 1; + optional uint32 column = 2; } message HeaderWithReferences { - string header = 1; - uint32 references = 2; + optional string header = 1; + optional uint32 references = 2; } message RelationsRequest { repeated string subjects = 1; - uint32 predicate = 2; - uint32 limit = 3; + optional uint32 predicate = 2; + optional uint32 limit = 3; } // The response is a stream of reference messages, and one terminating has_more @@ -135,6 +123,6 @@ message RelationsReply { // This struct does not mirror clangd::Relation but rather the arguments of // SymbolIndex::relations callback. message Relation { - string subject_id = 1; - Symbol object = 2; + optional string subject_id = 1; + optional Symbol object = 2; } diff --git a/clang-tools-extra/clangd/index/remote/Service.proto b/clang-tools-extra/clangd/index/remote/Service.proto new file mode 100644 index 0000000000000..4e39ff9ec6660 --- /dev/null +++ b/clang-tools-extra/clangd/index/remote/Service.proto @@ -0,0 +1,26 @@ +//===--- Service.proto - Remote index service definition ------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +syntax = "proto2"; + +package clang.clangd.remote.v1; + +import "Index.proto"; + +// Semantics of SymbolIndex match clangd::SymbolIndex with all required +// structures corresponding to their clangd::* counterparts. +service SymbolIndex { + rpc Lookup(LookupRequest) returns (stream LookupReply) {} + + rpc FuzzyFind(FuzzyFindRequest) returns (stream FuzzyFindReply) {} + + rpc Refs(RefsRequest) returns (stream RefsReply) {} + + rpc Relations(RelationsRequest) returns (stream RelationsReply) {} +} + diff --git a/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt index 75e57edd45d94..7b78ba3bb6903 100644 --- a/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/remote/marshalling/CMakeLists.txt @@ -2,12 +2,12 @@ add_clang_library(clangdRemoteMarshalling Marshalling.cpp LINK_LIBS - RemoteIndexProtos + RemoteIndexProto protobuf clangDaemon clangdSupport DEPENDS - RemoteIndexProtos + RemoteIndexProto ) diff --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp index 6285022fc0a85..296f99cdfa38f 100644 --- a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp +++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp @@ -11,6 +11,7 @@ #include "Index.pb.h" #include "Protocol.h" #include "index/Index.h" +#include "index/Ref.h" #include "index/Serialization.h" #include "index/Symbol.h" #include "index/SymbolID.h" @@ -31,6 +32,12 @@ namespace clang { namespace clangd { namespace remote { +using llvm::sys::path::append; +using llvm::sys::path::convert_to_slash; +using llvm::sys::path::is_absolute; +using llvm::sys::path::replace_path_prefix; +using llvm::sys::path::Style; + namespace { template @@ -50,23 +57,20 @@ llvm::Expected> getIDs(IDRange IDs) { Marshaller::Marshaller(llvm::StringRef RemoteIndexRoot, llvm::StringRef LocalIndexRoot) : Strings(Arena) { - llvm::StringRef PosixSeparator = - llvm::sys::path::get_separator(llvm::sys::path::Style::posix); + llvm::StringRef PosixSeparator = get_separator(Style::posix); if (!RemoteIndexRoot.empty()) { - assert(llvm::sys::path::is_absolute(RemoteIndexRoot)); - this->RemoteIndexRoot = llvm::sys::path::convert_to_slash( - RemoteIndexRoot, llvm::sys::path::Style::windows); - llvm::StringRef Path(*this->RemoteIndexRoot); - if (!Path.endswith(PosixSeparator)) - *this->RemoteIndexRoot += PosixSeparator; + assert(is_absolute(RemoteIndexRoot)); + this->RemoteIndexRoot = convert_to_slash(RemoteIndexRoot, Style::windows); + llvm::StringRef Path(this->RemoteIndexRoot); + if (!is_separator(this->RemoteIndexRoot.back(), Style::posix)) + this->RemoteIndexRoot += PosixSeparator; } if (!LocalIndexRoot.empty()) { - assert(llvm::sys::path::is_absolute(LocalIndexRoot)); - this->LocalIndexRoot = llvm::sys::path::convert_to_slash( - LocalIndexRoot, llvm::sys::path::Style::windows); - llvm::StringRef Path(*this->LocalIndexRoot); - if (!Path.endswith(PosixSeparator)) - *this->LocalIndexRoot += PosixSeparator; + assert(is_absolute(LocalIndexRoot)); + this->LocalIndexRoot = convert_to_slash(LocalIndexRoot, Style::windows); + llvm::StringRef Path(this->LocalIndexRoot); + if (!is_separator(this->LocalIndexRoot.back(), Style::posix)) + this->LocalIndexRoot += PosixSeparator; } assert(!RemoteIndexRoot.empty() || !LocalIndexRoot.empty()); } @@ -83,7 +87,7 @@ Marshaller::fromProtobuf(const LookupRequest *Message) { llvm::Expected Marshaller::fromProtobuf(const FuzzyFindRequest *Message) { - assert(RemoteIndexRoot); + assert(!RemoteIndexRoot.empty()); clangd::FuzzyFindRequest Result; Result.Query = Message->query(); for (const auto &Scope : Message->scopes()) @@ -93,8 +97,8 @@ Marshaller::fromProtobuf(const FuzzyFindRequest *Message) { Result.Limit = Message->limit(); Result.RestrictForCodeCompletion = Message->restricted_for_code_completion(); for (const auto &Path : Message->proximity_paths()) { - llvm::SmallString<256> LocalPath = llvm::StringRef(*RemoteIndexRoot); - llvm::sys::path::append(LocalPath, Path); + llvm::SmallString<256> LocalPath = llvm::StringRef(RemoteIndexRoot); + append(LocalPath, Path); // FuzzyFindRequest requires proximity paths to have platform-native format // in order for SymbolIndex to process the query correctly. llvm::sys::path::native(LocalPath); @@ -112,7 +116,10 @@ Marshaller::fromProtobuf(const RefsRequest *Message) { if (!IDs) return IDs.takeError(); Req.IDs = std::move(*IDs); - Req.Filter = static_cast(Message->filter()); + if (Message->has_filter()) + Req.Filter = static_cast(Message->filter()); + else + Req.Filter = clangd::RefKind::All; if (Message->limit()) Req.Limit = Message->limit(); return Req; @@ -125,6 +132,8 @@ Marshaller::fromProtobuf(const RelationsRequest *Message) { if (!IDs) return IDs.takeError(); Req.Subjects = std::move(*IDs); + if (!Message->has_predicate()) + return error("RelationsRequest requires RelationKind predicate."); Req.Predicate = static_cast(Message->predicate()); if (Message->limit()) Req.Limit = Message->limit(); @@ -177,7 +186,7 @@ llvm::Expected Marshaller::fromProtobuf(const Ref &Message) { if (!Location) return Location.takeError(); Result.Location = *Location; - Result.Kind = static_cast(Message.kind()); + Result.Kind = static_cast(Message.kind()); return Result; } @@ -202,7 +211,7 @@ LookupRequest Marshaller::toProtobuf(const clangd::LookupRequest &From) { } FuzzyFindRequest Marshaller::toProtobuf(const clangd::FuzzyFindRequest &From) { - assert(LocalIndexRoot); + assert(!LocalIndexRoot.empty()); FuzzyFindRequest RPCRequest; RPCRequest.set_query(From.Query); for (const auto &Scope : From.Scopes) @@ -213,9 +222,9 @@ FuzzyFindRequest Marshaller::toProtobuf(const clangd::FuzzyFindRequest &From) { RPCRequest.set_restricted_for_code_completion(From.RestrictForCodeCompletion); for (const auto &Path : From.ProximityPaths) { llvm::SmallString<256> RelativePath = llvm::StringRef(Path); - if (llvm::sys::path::replace_path_prefix(RelativePath, *LocalIndexRoot, "")) - RPCRequest.add_proximity_paths(llvm::sys::path::convert_to_slash( - RelativePath, llvm::sys::path::Style::windows)); + if (replace_path_prefix(RelativePath, LocalIndexRoot, "")) + RPCRequest.add_proximity_paths( + convert_to_slash(RelativePath, Style::windows)); } for (const auto &Type : From.PreferredTypes) RPCRequest.add_preferred_types(Type); @@ -301,20 +310,20 @@ llvm::Expected Marshaller::toProtobuf(const clangd::SymbolID &Subject, llvm::Expected Marshaller::relativePathToURI(llvm::StringRef RelativePath) { - assert(LocalIndexRoot); - assert(RelativePath == llvm::sys::path::convert_to_slash(RelativePath)); + assert(!LocalIndexRoot.empty()); + assert(RelativePath == convert_to_slash(RelativePath)); if (RelativePath.empty()) return error("Empty relative path."); - if (llvm::sys::path::is_absolute(RelativePath, llvm::sys::path::Style::posix)) + if (is_absolute(RelativePath, Style::posix)) return error("RelativePath '{0}' is absolute.", RelativePath); - llvm::SmallString<256> FullPath = llvm::StringRef(*LocalIndexRoot); - llvm::sys::path::append(FullPath, RelativePath); + llvm::SmallString<256> FullPath = llvm::StringRef(LocalIndexRoot); + append(FullPath, RelativePath); auto Result = URI::createFile(FullPath); return Result.toString(); } llvm::Expected Marshaller::uriToRelativePath(llvm::StringRef URI) { - assert(RemoteIndexRoot); + assert(!RemoteIndexRoot.empty()); auto ParsedURI = URI::parse(URI); if (!ParsedURI) return ParsedURI.takeError(); @@ -323,14 +332,12 @@ llvm::Expected Marshaller::uriToRelativePath(llvm::StringRef URI) { llvm::SmallString<256> Result = ParsedURI->body(); llvm::StringRef Path(Result); // Check for Windows paths (URI=file:///X:/path => Body=/X:/path) - if (llvm::sys::path::is_absolute(Path.substr(1), - llvm::sys::path::Style::windows)) + if (is_absolute(Path.substr(1), Style::windows)) Result = Path.drop_front(); - if (!llvm::sys::path::replace_path_prefix(Result, *RemoteIndexRoot, "")) + if (!replace_path_prefix(Result, RemoteIndexRoot, "")) return error("File path '{0}' doesn't start with '{1}'.", Result.str(), - *RemoteIndexRoot); - assert(Result == llvm::sys::path::convert_to_slash( - Result, llvm::sys::path::Style::windows)); + RemoteIndexRoot); + assert(Result == convert_to_slash(Result, Style::windows)); return std::string(Result); } diff --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h index 18ce6074264c0..e827b4c155a20 100644 --- a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h +++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h @@ -95,8 +95,8 @@ class Marshaller { /// of them can be missing (if the machines are different they don't know each /// other's specifics and will only do one-way translation), but both can not /// be missing at the same time. - llvm::Optional RemoteIndexRoot; - llvm::Optional LocalIndexRoot; + std::string RemoteIndexRoot; + std::string LocalIndexRoot; llvm::BumpPtrAllocator Arena; llvm::UniqueStringSaver Strings; }; diff --git a/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt b/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt index 9ca1f34730877..595c406eff0f1 100644 --- a/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt +++ b/clang-tools-extra/clangd/index/remote/server/CMakeLists.txt @@ -5,7 +5,8 @@ add_clang_executable(clangd-index-server Server.cpp DEPENDS - RemoteIndexProtos + RemoteIndexProto + RemoteIndexServiceProto ) target_link_libraries(clangd-index-server @@ -13,7 +14,8 @@ target_link_libraries(clangd-index-server clangDaemon clangdSupport - RemoteIndexProtos + RemoteIndexProto + RemoteIndexServiceProto clangdRemoteMarshalling grpc++ diff --git a/clang-tools-extra/clangd/index/remote/server/Server.cpp b/clang-tools-extra/clangd/index/remote/server/Server.cpp index d8cf542496627..7b68549a4afd9 100644 --- a/clang-tools-extra/clangd/index/remote/server/Server.cpp +++ b/clang-tools-extra/clangd/index/remote/server/Server.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Index.pb.h" +#include "Service.grpc.pb.h" #include "index/Index.h" #include "index/Serialization.h" #include "index/Symbol.h" @@ -32,8 +33,6 @@ #include #include -#include "Index.grpc.pb.h" - namespace clang { namespace clangd { namespace remote { @@ -73,7 +72,7 @@ llvm::cl::opt ServerAddress( "server-address", llvm::cl::init("0.0.0.0:50051"), llvm::cl::desc("Address of the invoked server. Defaults to 0.0.0.0:50051")); -class RemoteIndexServer final : public SymbolIndex::Service { +class RemoteIndexServer final : public v1::SymbolIndex::Service { public: RemoteIndexServer(clangd::SymbolIndex &Index, llvm::StringRef IndexRoot) : Index(Index) { diff --git a/clang-tools-extra/clangd/test/CMakeLists.txt b/clang-tools-extra/clangd/test/CMakeLists.txt index 878408cc5483a..ade42ac457e03 100644 --- a/clang-tools-extra/clangd/test/CMakeLists.txt +++ b/clang-tools-extra/clangd/test/CMakeLists.txt @@ -21,6 +21,10 @@ if(CLANGD_BUILD_XPC) list(APPEND CLANGD_TEST_DEPS ClangdXpcUnitTests) endif() +if(CLANGD_ENABLE_REMOTE) + list(APPEND CLANGD_TEST_DEPS clangd-index-server) +endif() + foreach(dep FileCheck count not llvm-config) if(TARGET ${dep}) list(APPEND CLANGD_TEST_DEPS ${dep}) diff --git a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp index cc0ca6f54a7f2..b25d3fde00025 100644 --- a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp @@ -230,49 +230,6 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) { FileURI("unittest:///root/B.cc")})); } -TEST_F(BackgroundIndexTest, RelationsMultiFile) { - MockFS FS; - FS.Files[testPath("root/Base.h")] = "class Base {};"; - FS.Files[testPath("root/A.cc")] = R"cpp( - #include "Base.h" - class A : public Base {}; - )cpp"; - FS.Files[testPath("root/B.cc")] = R"cpp( - #include "Base.h" - class B : public Base {}; - )cpp"; - - llvm::StringMap Storage; - size_t CacheHits = 0; - MemoryShardStorage MSS(Storage, CacheHits); - OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Index(FS, CDB, [&](llvm::StringRef) { return &MSS; }, - /*Opts=*/{}); - - tooling::CompileCommand Cmd; - Cmd.Filename = testPath("root/A.cc"); - Cmd.Directory = testPath("root"); - Cmd.CommandLine = {"clang++", Cmd.Filename}; - CDB.setCompileCommand(testPath("root/A.cc"), Cmd); - ASSERT_TRUE(Index.blockUntilIdleForTest()); - - Cmd.Filename = testPath("root/B.cc"); - Cmd.CommandLine = {"clang++", Cmd.Filename}; - CDB.setCompileCommand(testPath("root/B.cc"), Cmd); - ASSERT_TRUE(Index.blockUntilIdleForTest()); - - auto HeaderShard = MSS.loadShard(testPath("root/Base.h")); - EXPECT_NE(HeaderShard, nullptr); - SymbolID Base = findSymbol(*HeaderShard->Symbols, "Base").ID; - - RelationsRequest Req; - Req.Subjects.insert(Base); - Req.Predicate = RelationKind::BaseOf; - uint32_t Results = 0; - Index.relations(Req, [&](const SymbolID &, const Symbol &) { ++Results; }); - EXPECT_EQ(Results, 2u); -} - TEST_F(BackgroundIndexTest, MainFileRefs) { MockFS FS; FS.Files[testPath("root/A.h")] = R"cpp( diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index de8eaca6059fa..bf964484bc6c6 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -88,6 +88,7 @@ add_unittest(ClangdUnitTests ClangdTests TestFS.cpp TestIndex.cpp TestTU.cpp + TestWorkspace.cpp TypeHierarchyTests.cpp TweakTests.cpp TweakTesting.cpp diff --git a/clang-tools-extra/clangd/unittests/FileIndexTests.cpp b/clang-tools-extra/clangd/unittests/FileIndexTests.cpp index 4abe0bf5e5dc8..80c4798fc65bf 100644 --- a/clang-tools-extra/clangd/unittests/FileIndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/FileIndexTests.cpp @@ -14,6 +14,7 @@ #include "SyncAPI.h" #include "TestFS.h" #include "TestTU.h" +#include "TestWorkspace.h" #include "URI.h" #include "index/CanonicalIncludes.h" #include "index/FileIndex.h" @@ -426,6 +427,33 @@ TEST(FileIndexTest, Relations) { EXPECT_EQ(Results, 1u); } +TEST(FileIndexTest, RelationsMultiFile) { + TestWorkspace Workspace; + Workspace.addSource("Base.h", "class Base {};"); + Workspace.addMainFile("A.cpp", R"cpp( + #include "Base.h" + class A : public Base {}; + )cpp"); + Workspace.addMainFile("B.cpp", R"cpp( + #include "Base.h" + class B : public Base {}; + )cpp"); + + auto Index = Workspace.index(); + FuzzyFindRequest FFReq; + FFReq.Query = "Base"; + FFReq.AnyScope = true; + SymbolID Base; + Index->fuzzyFind(FFReq, [&](const Symbol &S) { Base = S.ID; }); + + RelationsRequest Req; + Req.Subjects.insert(Base); + Req.Predicate = RelationKind::BaseOf; + uint32_t Results = 0; + Index->relations(Req, [&](const SymbolID &, const Symbol &) { ++Results; }); + EXPECT_EQ(Results, 2u); +} + TEST(FileIndexTest, ReferencesInMainFileWithPreamble) { TestTU TU; TU.HeaderCode = "class Foo{};"; diff --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp index 81b6b43da94b4..d0f011ef56497 100644 --- a/clang-tools-extra/clangd/unittests/TestTU.cpp +++ b/clang-tools-extra/clangd/unittests/TestTU.cpp @@ -80,7 +80,8 @@ void deleteModuleCache(const std::string ModuleCachePath) { } } -std::shared_ptr TestTU::preamble() const { +std::shared_ptr +TestTU::preamble(PreambleParsedCallback PreambleCallback) const { MockFS FS; auto Inputs = inputs(FS); IgnoreDiagnostics Diags; @@ -91,8 +92,7 @@ std::shared_ptr TestTU::preamble() const { auto ModuleCacheDeleter = llvm::make_scope_exit( std::bind(deleteModuleCache, CI->getHeaderSearchOpts().ModuleCachePath)); return clang::clangd::buildPreamble(testPath(Filename), *CI, Inputs, - /*StoreInMemory=*/true, - /*PreambleCallback=*/nullptr); + /*StoreInMemory=*/true, PreambleCallback); } ParsedAST TestTU::build() const { diff --git a/clang-tools-extra/clangd/unittests/TestTU.h b/clang-tools-extra/clangd/unittests/TestTU.h index dd0cecc406acb..f383e693408c3 100644 --- a/clang-tools-extra/clangd/unittests/TestTU.h +++ b/clang-tools-extra/clangd/unittests/TestTU.h @@ -79,7 +79,8 @@ struct TestTU { // By default, build() will report Error diagnostics as GTest errors. // Suppress this behavior by adding an 'error-ok' comment to the code. ParsedAST build() const; - std::shared_ptr preamble() const; + std::shared_ptr + preamble(PreambleParsedCallback PreambleCallback = nullptr) const; ParseInputs inputs(MockFS &FS) const; SymbolSlab headerSymbols() const; RefSlab headerRefs() const; diff --git a/clang-tools-extra/clangd/unittests/TestWorkspace.cpp b/clang-tools-extra/clangd/unittests/TestWorkspace.cpp new file mode 100644 index 0000000000000..52cf45f5be244 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/TestWorkspace.cpp @@ -0,0 +1,49 @@ +//===--- TestWorkspace.cpp - Utility for writing multi-file tests -*- C++-*===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestWorkspace.h" + +namespace clang { +namespace clangd { + +std::unique_ptr TestWorkspace::index() { + auto Index = std::make_unique(); + for (const auto &Input : Inputs) { + if (!Input.second.IsMainFile) + continue; + TU.Code = Input.second.Code; + TU.Filename = Input.first().str(); + TU.preamble([&](ASTContext &Ctx, std::shared_ptr PP, + const CanonicalIncludes &CanonIncludes) { + Index->updatePreamble(testPath(Input.first()), "null", Ctx, PP, + CanonIncludes); + }); + ParsedAST MainAST = TU.build(); + Index->updateMain(testPath(Input.first()), MainAST); + } + return Index; +} + +Optional TestWorkspace::openFile(llvm::StringRef Filename) { + auto It = Inputs.find(Filename); + if (It == Inputs.end()) { + ADD_FAILURE() << "Accessing non-existing file: " << Filename; + return llvm::None; + } + TU.Code = It->second.Code; + TU.Filename = It->first().str(); + return TU.build(); +} + +void TestWorkspace::addInput(llvm::StringRef Filename, + const SourceFile &Input) { + Inputs.insert(std::make_pair(Filename, Input)); + TU.AdditionalFiles.insert(std::make_pair(Filename, Input.Code)); +} +} // namespace clangd +} // namespace clang \ No newline at end of file diff --git a/clang-tools-extra/clangd/unittests/TestWorkspace.h b/clang-tools-extra/clangd/unittests/TestWorkspace.h new file mode 100644 index 0000000000000..eb5112f198dd7 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/TestWorkspace.h @@ -0,0 +1,59 @@ +//===--- TestWorkspace.h - Utility for writing multi-file tests --*- 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 +// +//===----------------------------------------------------------------------===// +// +// TestWorkspace builds on TestTU to provide a way to write tests involving +// several related files with inclusion relationships between them. +// +// The tests can exercise both index and AST based operations. +// +//===---------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTWORKSPACE_H +#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTWORKSPACE_H + +#include "TestFS.h" +#include "TestTU.h" +#include "index/FileIndex.h" +#include "index/Index.h" +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace clang { +namespace clangd { + +class TestWorkspace { +public: + // The difference between addSource() and addMainFile() is that only main + // files will be indexed. + void addSource(llvm::StringRef Filename, llvm::StringRef Code) { + addInput(Filename.str(), {Code.str(), /*IsMainFile=*/false}); + } + void addMainFile(llvm::StringRef Filename, llvm::StringRef Code) { + addInput(Filename.str(), {Code.str(), /*IsMainFile=*/true}); + } + + std::unique_ptr index(); + + Optional openFile(llvm::StringRef Filename); + +private: + struct SourceFile { + std::string Code; + bool IsMainFile = false; + }; + llvm::StringMap Inputs; + TestTU TU; + + void addInput(llvm::StringRef Filename, const SourceFile &Input); +}; + +} // namespace clangd +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTWORKSPACE_H diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp index 7a70bc18a28c8..9055529c7a3fd 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp @@ -405,3 +405,58 @@ void negativeInitialzedFromFreeFunctionWithNonDefaultArg() { ExpensiveToCopyType Orig; const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg(&Orig); } + +namespace std { +inline namespace __1 { + +template +class function; +template +class function { +public: + function(); + function(const function &other); + R operator()(Args &&...args) const; +}; + +} // namespace __1 +} // namespace std + +void negativeStdFunction() { + std::function Orig; + std::function Copy = Orig; + int i = Orig(); +} + +using Functor = std::function; + +void negativeAliasedStdFunction() { + Functor Orig; + Functor Copy = Orig; + int i = Orig(); +} + +typedef std::function TypedefFunc; + +void negativeTypedefedStdFunction() { + TypedefFunc Orig; + TypedefFunc Copy = Orig; + int i = Orig(); +} + +namespace fake { +namespace std { +template +struct function { + // Custom copy constructor makes it expensive to copy; + function(const function &); +}; +} // namespace std + +void positiveFakeStdFunction(std::function F) { + auto Copy = F; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: local copy 'Copy' of the variable 'F' is never modified; + // CHECK-FIXES: const auto& Copy = F; +} + +} // namespace fake diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 7592d84ea9ed7..9e40cf1b2a976 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -449,7 +449,6 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) PATTERN "*.def" PATTERN "*.h" PATTERN "config.h" EXCLUDE - PATTERN ".svn" EXCLUDE ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/clang diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 86bc9f637ab7e..6864f6058a3ff 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -3335,6 +3335,8 @@ X86 .. option:: -mtsxldtrk, -mno-tsxldtrk +.. option:: -muintr, -mno-uintr + .. option:: -mvaes, -mno-vaes .. option:: -mvpclmulqdq, -mno-vpclmulqdq diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 540cf91326056..2a7beba73b697 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -190,7 +190,8 @@ X86 Support in Clang - The x86 intrinsics ``__rorb``, ``__rorw``, ``__rord``, ``__rorq`, ``_rotr``, ``_rotwr`` and ``_lrotr`` may now be used within constant expressions. -- Support for ``-march=sapphirerapids`` was added. +- Support for ``-march=alderlake``, ``-march=sapphirerapids`` and + ``-march=znver3`` was added. - Support for ``-march=x86-64-v[234]`` has been added. See :doc:`UsersManual` for details about these micro-architecture levels. @@ -200,6 +201,10 @@ X86 Support in Clang implies -mtune=. -mtune=generic is the default with no -march or -mtune specified. +- Support for ``HRESET`` instructions has been added. + +- Support for ``UINTR`` instructions has been added. + Internal API Changes -------------------- diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 9726a25f7f633..5d18435aab6ca 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1386,7 +1386,7 @@ Note that floating-point operations performed as part of constant initialization Details: * ``precise`` Disables optimizations that are not value-safe on floating-point data, although FP contraction (FMA) is enabled (``-ffp-contract=fast``). This is the default behavior. - * ``strict`` Enables ``-frounding-math`` and ``-ffp-exception-behavior=strict``, and disables contractions (FMA). All of the ``-ffast-math`` enablements are disabled. + * ``strict`` Enables ``-frounding-math`` and ``-ffp-exception-behavior=strict``, and disables contractions (FMA). All of the ``-ffast-math`` enablements are disabled. Enables ``STDC FENV_ACCESS``: by default ``FENV_ACCESS`` is disabled. This option setting behaves as though ``#pragma STDC FENV_ACESS ON`` appeared at the top of the source file. * ``fast`` Behaves identically to specifying both ``-ffast-math`` and ``ffp-contract=fast`` Note: If your command line specifies multiple instances @@ -1408,6 +1408,44 @@ Note that floating-point operations performed as part of constant initialization * ``strict`` The compiler ensures that all transformations strictly preserve the floating point exception semantics of the original code. +.. _fp-constant-eval: + +A note about Floating Point Constant Evaluation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In C, the only place floating point operations are guaranteed to be evaluated +during translation is in the initializers of variables of static storage +duration, which are all notionally initialized before the program begins +executing (and thus before a non-default floating point environment can be +entered). But C++ has many more contexts where floating point constant +evaluation occurs. Specifically: for static/thread-local variables, +first try evaluating the initializer in a constant context, including in the +constant floating point environment (just like in C), and then, if that fails, +fall back to emitting runtime code to perform the initialization (which might +in general be in a different floating point environment). + +Consider this example when compiled with ``-frounding-math`` + + .. code-block:: console + +constexpr float func_01(float x, float y) { + return x + y; +} +float V1 = func_01(1.0F, 0x0.000001p0F); + +The C++ rule is that initializers for static storage duration variables are +first evaluated during translation (therefore, in the default rounding mode), +and only evaluated at runtime (and therefore in the runtime rounding mode) if +the compile-time evaluation fails. This is in line with the C rules; +C11 F.8.5 says: *All computation for automatic initialization is done (as if) +at execution time; thus, it is affected by any operative modes and raises +floating-point exceptions as required by IEC 60559 (provided the state for the +FENV_ACCESS pragma is β€˜β€˜on’’). All computation for initialization of objects +that have static or thread storage duration is done (as if) at translation +time.* C++ generalizes this by adding another phase of initialization +(at runtime) if the translation-time initialization fails, but the +translation-time evaluation of the initializer of succeeds, it will be +treated as a constant initializer. .. _controlling-code-generation: diff --git a/clang/examples/clang-interpreter/main.cpp b/clang/examples/clang-interpreter/main.cpp index 6b4cdca15fb09..342d42089472c 100644 --- a/clang/examples/clang-interpreter/main.cpp +++ b/clang/examples/clang-interpreter/main.cpp @@ -72,6 +72,11 @@ class SimpleJIT { } public: + ~SimpleJIT() { + if (auto Err = ES.endSession()) + ES.reportError(std::move(Err)); + } + static Expected> Create() { auto JTMB = JITTargetMachineBuilder::detectHost(); if (!JTMB) diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 0ee48f35a20a1..6cda588ffe748 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -235,8 +235,10 @@ class APValue { struct UninitArray {}; struct UninitStruct {}; - friend class ASTReader; + friend class ASTRecordReader; friend class ASTWriter; + friend class ASTImporter; + friend class ASTNodeImporter; private: ValueKind Kind; @@ -569,11 +571,9 @@ class APValue { *(APFixedPoint *)(char *)Data.buffer = std::move(FX); } void setVector(const APValue *E, unsigned N) { - assert(isVector() && "Invalid accessor"); - ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; - ((Vec*)(char*)Data.buffer)->NumElts = N; + MutableArrayRef InternalElts = setVectorUninit(N); for (unsigned i = 0; i != N; ++i) - ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; + InternalElts[i] = E[i]; } void setComplexInt(APSInt R, APSInt I) { assert(R.getBitWidth() == I.getBitWidth() && @@ -594,11 +594,7 @@ class APValue { void setLValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr); - void setUnion(const FieldDecl *Field, const APValue &Value) { - assert(isUnion() && "Invalid accessor"); - ((UnionData*)(char*)Data.buffer)->Field = Field; - *((UnionData*)(char*)Data.buffer)->Value = Value; - } + void setUnion(const FieldDecl *Field, const APValue &Value); void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) { ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; @@ -656,6 +652,24 @@ class APValue { new ((void*)(char*)Data.buffer) AddrLabelDiffData(); Kind = AddrLabelDiff; } + +private: + /// The following functions are used as part of initialization, during + /// deserialization and importing. Reserve the space so that it can be + /// filled in by those steps. + MutableArrayRef setVectorUninit(unsigned N) { + assert(isVector() && "Invalid accessor"); + Vec *V = ((Vec *)(char *)Data.buffer); + V->Elts = new APValue[N]; + V->NumElts = N; + return {V->Elts, V->NumElts}; + } + MutableArrayRef + setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + MutableArrayRef + setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size); }; } // end namespace clang. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 97facd5d3b68d..75daa122deebc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -289,8 +289,8 @@ class ASTContext : public RefCountedBase { /// Mapping from GUIDs to the corresponding MSGuidDecl. mutable llvm::FoldingSet MSGuidDecls; - /// Used to cleanups APValues stored in the AST. - mutable llvm::SmallVector APValueCleanups; + /// Mapping from APValues to the corresponding TemplateParamObjects. + mutable llvm::FoldingSet TemplateParamObjectDecls; /// A cache mapping a string value to a StringLiteral object with the same /// value. @@ -2876,6 +2876,11 @@ class ASTContext : public RefCountedBase { /// GUID value. MSGuidDecl *getMSGuidDecl(MSGuidDeclParts Parts) const; + /// Return the template parameter object of the given type with the given + /// value. + TemplateParamObjectDecl *getTemplateParamObjectDecl(QualType T, + const APValue &V) const; + /// Parses the target attributes passed in, and returns only the ones that are /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 205d7ec67754f..a6d822ba2ea6d 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H +#include "clang/AST/APValue.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" @@ -503,6 +504,13 @@ class TypeSourceInfo; /// "to" context, or the import error. llvm::Expected Import(const CXXBaseSpecifier *FromSpec); + /// Import the given APValue from the "from" context into + /// the "to" context. + /// + /// \return the equivalent APValue in the "to" context or the import + /// error. + llvm::Expected Import(const APValue &FromValue); + /// Import the definition of the given declaration, including all of /// the declarations it contains. LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From); diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index d24e11aab8170..e11fe417d9bb1 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2254,10 +2254,6 @@ class FunctionDecl : public DeclaratorDecl, bool usesSEHTry() const { return FunctionDeclBits.UsesSEHTry; } void setUsesSEHTry(bool UST) { FunctionDeclBits.UsesSEHTry = UST; } - /// Indicates the function uses Floating Point constrained intrinsics - bool usesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; } - void setUsesFPIntrin(bool Val) { FunctionDeclBits.UsesFPIntrin = Val; } - /// Whether this function has been deleted. /// /// A function that is "deleted" (via the C++0x "= delete" syntax) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 5f35257390912..641647659c17e 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3226,7 +3226,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl { static bool classofKind(Kind K) { return K == VarTemplate; } }; -// \brief Declaration of a C++2a concept. +/// Declaration of a C++2a concept. class ConceptDecl : public TemplateDecl, public Mergeable { protected: Expr *ConstraintExpr; @@ -3255,6 +3255,9 @@ class ConceptDecl : public TemplateDecl, public Mergeable { return isa(getTemplateParameters()->getParam(0)); } + ConceptDecl *getCanonicalDecl() override { return getFirstDecl(); } + const ConceptDecl *getCanonicalDecl() const { return getFirstDecl(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Concept; } @@ -3264,6 +3267,74 @@ class ConceptDecl : public TemplateDecl, public Mergeable { friend class ASTDeclWriter; }; +/// A template parameter object. +/// +/// Template parameter objects represent values of class type used as template +/// arguments. There is one template parameter object for each such distinct +/// value used as a template argument across the program. +/// +/// \code +/// struct A { int x, y; }; +/// template struct S; +/// S s1; +/// S s2; // same type, argument is same TemplateParamObjectDecl. +/// \endcode +class TemplateParamObjectDecl : public ValueDecl, + public Mergeable, + public llvm::FoldingSetNode { +private: + /// The value of this template parameter object. + APValue Value; + + TemplateParamObjectDecl(DeclContext *DC, QualType T, const APValue &V) + : ValueDecl(TemplateParamObject, DC, SourceLocation(), DeclarationName(), + T), + Value(V) {} + + static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T, + const APValue &V); + static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + /// Only ASTContext::getTemplateParamObjectDecl and deserialization + /// create these. + friend class ASTContext; + friend class ASTReader; + friend class ASTDeclReader; + +public: + /// Print this template parameter object in a human-readable format. + void printName(llvm::raw_ostream &OS) const override; + + /// Print this object as an equivalent expression. + void printAsExpr(llvm::raw_ostream &OS) const; + + /// Print this object as an initializer suitable for a variable of the + /// object's type. + void printAsInit(llvm::raw_ostream &OS) const; + + const APValue &getValue() const { return Value; } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType T, + const APValue &V) { + ID.AddPointer(T.getCanonicalType().getAsOpaquePtr()); + V.Profile(ID); + } + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getType(), getValue()); + } + + TemplateParamObjectDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const TemplateParamObjectDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == TemplateParamObject; } +}; + inline NamedDecl *getAsNamedDecl(TemplateParameter P) { if (auto *PD = P.dyn_cast()) return PD; diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 31a48b7c8a7cb..5bbcbde9f9090 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -711,13 +711,26 @@ class Expr : public ValueStmt { ArrayRef Args, const Expr *This = nullptr) const; - /// Indicates how the constant expression will be used. - enum ConstExprUsage { EvaluateForCodeGen, EvaluateForMangling }; + enum class ConstantExprKind { + /// An integer constant expression (an array bound, enumerator, case value, + /// bit-field width, or similar) or similar. + Normal, + /// A non-class template argument. Such a value is only used for mangling, + /// not for code generation, so can refer to dllimported functions. + NonClassTemplateArgument, + /// A class template argument. Such a value is used for code generation. + ClassTemplateArgument, + /// An immediate invocation. The destruction of the end result of this + /// evaluation is not part of the evaluation, but all other temporaries + /// are destroyed. + ImmediateInvocation, + }; - /// Evaluate an expression that is required to be a constant expression. - bool EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, - const ASTContext &Ctx, - bool InPlace = false) const; + /// Evaluate an expression that is required to be a constant expression. Does + /// not check the syntactic constraints for C and C++98 constant expressions. + bool EvaluateAsConstantExpr( + EvalResult &Result, const ASTContext &Ctx, + ConstantExprKind Kind = ConstantExprKind::Normal) const; /// If the current Expr is a pointer, this will try to statically /// determine the number of bytes available where the pointer is pointing. @@ -971,6 +984,8 @@ static_assert(llvm::PointerLikeTypeTraits::NumLowBitsAvailable <= llvm::detail::ConstantLog2::value, "PointerLikeTypeTraits assumes too much alignment."); +using ConstantExprKind = Expr::ConstantExprKind; + //===----------------------------------------------------------------------===// // Wrapper Expressions. //===----------------------------------------------------------------------===// @@ -2060,6 +2075,10 @@ class PredefinedExpr final } static StringRef getIdentKindName(IdentKind IK); + StringRef getIdentKindName() const { + return getIdentKindName(getIdentKind()); + } + static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl); static std::string ComputeName(ASTContext &Context, IdentKind IK, const QualType Ty); diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 926021e9c6ed6..2144279f132be 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4233,8 +4233,10 @@ class SubstNonTypeTemplateParmExpr : public Expr { friend class ASTReader; friend class ASTStmtReader; - /// The replaced parameter. - NonTypeTemplateParmDecl *Param; + /// The replaced parameter and a flag indicating if it was a reference + /// parameter. For class NTTPs, we can't determine that based on the value + /// category alone. + llvm::PointerIntPair ParamAndRef; /// The replacement expression. Stmt *Replacement; @@ -4245,10 +4247,10 @@ class SubstNonTypeTemplateParmExpr : public Expr { public: SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, SourceLocation Loc, - NonTypeTemplateParmDecl *Param, + NonTypeTemplateParmDecl *Param, bool RefParam, Expr *Replacement) : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), - Param(Param), Replacement(Replacement) { + ParamAndRef(Param, RefParam), Replacement(Replacement) { SubstNonTypeTemplateParmExprBits.NameLoc = Loc; setDependence(computeDependence(this)); } @@ -4261,7 +4263,14 @@ class SubstNonTypeTemplateParmExpr : public Expr { Expr *getReplacement() const { return cast(Replacement); } - NonTypeTemplateParmDecl *getParameter() const { return Param; } + NonTypeTemplateParmDecl *getParameter() const { + return ParamAndRef.getPointer(); + } + + bool isReferenceParameter() const { return ParamAndRef.getInt(); } + + /// Determine the substituted type of the template parameter. + QualType getParameterType(const ASTContext &Ctx) const; static bool classof(const Stmt *s) { return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; @@ -4510,6 +4519,10 @@ class MaterializeTemporaryExpr : public Expr { return getValueKind() == VK_LValue; } + /// Determine whether this temporary object is usable in constant + /// expressions, as specified in C++20 [expr.const]p4. + bool isUsableInConstantExpressions(const ASTContext &Context) const; + SourceLocation getBeginLoc() const LLVM_READONLY { return getSubExpr()->getBeginLoc(); } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 6f07b92f25323..5e83cded06520 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1970,6 +1970,8 @@ DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) DEF_TRAVERSE_DECL(MSGuidDecl, {}) +DEF_TRAVERSE_DECL(TemplateParamObjectDecl, {}) + DEF_TRAVERSE_DECL(FieldDecl, { TRY_TO(TraverseDeclaratorHelper(D)); if (D->isBitField()) diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 51d51d707de4a..11886dcafa61f 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -145,6 +145,7 @@ using TypeLocMatcher = internal::Matcher; using NestedNameSpecifierMatcher = internal::Matcher; using NestedNameSpecifierLocMatcher = internal::Matcher; using CXXCtorInitializerMatcher = internal::Matcher; +using TemplateArgumentMatcher = internal::Matcher; using TemplateArgumentLocMatcher = internal::Matcher; /// @} diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index c26d2ed99dd23..77a800c28754c 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -634,7 +634,9 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) { /// At compile time, pointer literals are represented by symbolic names. class LiteralPtr : public SExpr { public: - LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {} + LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) { + assert(D && "ValueDecl must not be null"); + } LiteralPtr(const LiteralPtr &) = default; static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; } diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fb903290706db..05e9f4793abaf 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -748,7 +748,7 @@ def AnalyzerNoReturn : InheritableAttr { def Annotate : InheritableParamAttr { let Spellings = [Clang<"annotate">]; - let Args = [StringArgument<"Annotation">]; + let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">]; // Ensure that the annotate attribute can be used with // '#pragma clang attribute' even though it has no subject list. let PragmaAttributeSupport = 1; @@ -1849,6 +1849,18 @@ def SYCLIntelFPGASpeculatedIterations : Attr { let Documentation = [SYCLIntelFPGASpeculatedIterationsAttrDocs]; } +def SYCLIntelFPGANofusion : Attr { + let Spellings = [CXX11<"intel","nofusion">]; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let HasCustomTypeTransform = 1; + let AdditionalMembers = [{ + static const char *getName() { + return "nofusion"; + } + }]; + let Documentation = [SYCLIntelFPGANofusionAttrDocs]; +} + def IntelFPGALocalNonConstVar : SubsetSubjecthasLocalStorage() && S->getKind() != Decl::ImplicitParam && @@ -2809,6 +2821,14 @@ def PragmaClangRelroSection : InheritableAttr { let Documentation = [Undocumented]; } +def StrictFP : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + // Function uses strict floating point operations. + let Spellings = []; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + def PragmaClangTextSection : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b94d60a251cb7..e15e614278280 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2418,6 +2418,15 @@ used on the same loop in conjunction with disable_loop_pipelining. }]; } +def SYCLIntelFPGANofusionAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "intel::nofusion"; + let Content = [{ +This attribute applies to a loop. Indicates that the annotated +loop should not be fused with any adjacent loop. + }]; +} + def SYCLDeviceIndirectlyCallableDocs : Documentation { let Category = DocCatFunction; let Heading = "intel::device_indirectly_callable"; @@ -4405,6 +4414,10 @@ option. int bar(int y); // bar can be built with the stack protector. +A callee that has a stack protector will not be inlined into a +``__attribute__((no_stack_protector))`` caller, and vice-versa, even if the +callee is marked ``__attribute__((always_inline))``. + }]; } diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def index f66ae78f7e81f..3e186af82ff71 100644 --- a/clang/include/clang/Basic/BuiltinsX86_64.def +++ b/clang/include/clang/Basic/BuiltinsX86_64.def @@ -94,6 +94,12 @@ TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dUOiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fUOiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_directstore_u64, "vULi*ULi", "n", "movdiri") +// UINTR +TARGET_BUILTIN(__builtin_ia32_clui, "v", "n", "uintr") +TARGET_BUILTIN(__builtin_ia32_stui, "v", "n", "uintr") +TARGET_BUILTIN(__builtin_ia32_testui, "Uc", "n", "uintr") +TARGET_BUILTIN(__builtin_ia32_senduipi, "vUWi", "n", "uintr") + // AMX TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile") TARGET_BUILTIN(__builtin_ia32_tile_storeconfig, "vvC*", "n", "amx-tile") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 641b99edaed11..f5222b50fc7bf 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -348,7 +348,7 @@ CODEGENOPT(CodeViewGHash, 1, 0) ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining) // Vector functions library to use. -ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary) +ENUM_CODEGENOPT(VecLib, VectorLibrary, 3, NoLibrary) /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) @@ -356,6 +356,9 @@ ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) /// Bit size of immediate TLS offsets (0 == use the default). VALUE_CODEGENOPT(TLSSize, 8, 0) +/// The default stack protector guard offset to use. +VALUE_CODEGENOPT(StackProtectorGuardOffset, 32, (unsigned)-1) + /// Number of path components to strip when emitting checks. (0 == full /// filename) VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index ca391bf8f1861..764d0a17cb72e 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -54,11 +54,11 @@ class CodeGenOptions : public CodeGenOptionsBase { enum VectorLibrary { NoLibrary, // Don't use any vector library. Accelerate, // Use the Accelerate framework. + LIBMVEC, // GLIBC vector math library. MASSV, // IBM MASS vector library. SVML // Intel short vector math library. }; - enum ObjCDispatchMethodKind { Legacy = 0, NonLegacy = 1, @@ -327,6 +327,15 @@ class CodeGenOptions : public CodeGenOptionsBase { /// by sanitizer coverage pass. std::vector SanitizeCoverageAllowlistFiles; + /// The guard style used for stack protector to get a initial value, this + /// value usually be gotten from TLS or get from __stack_chk_guard, or some + /// other styles we may implement in the future. + std::string StackProtectorGuard; + + /// The TLS base register when StackProtectorGuard is "tls". + /// On x86 this can be "fs" or "gs". + std::string StackProtectorGuardReg; + /// Path to blocklist file specifying which objects /// (files, functions) listed for instrumentation by sanitizer /// coverage pass should actually not be instrumented. diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 866988ee3f015..4771a3549426b 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -41,6 +41,7 @@ def Named : DeclNode; def OMPDeclareReduction : DeclNode, DeclContext; def OMPDeclareMapper : DeclNode, DeclContext; def MSGuid : DeclNode; + def TemplateParamObject : DeclNode; def Declarator : DeclNode; def Field : DeclNode; def ObjCIvar : DeclNode; diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 231d597fe36a2..f6b936f5ccd9d 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -74,6 +74,8 @@ def note_constexpr_float_arithmetic : Note< "floating point arithmetic produces %select{an infinity|a NaN}0">; def note_constexpr_dynamic_rounding : Note< "cannot evaluate this expression if rounding mode is dynamic">; +def note_constexpr_float_arithmetic_strict : Note< + "compile time floating point arithmetic suppressed in strict evaluation modes">; def note_constexpr_pointer_subtraction_not_same_array : Note< "subtracted pointers are not elements of the same array">; def note_constexpr_pointer_subtraction_zero_size : Note< @@ -252,7 +254,7 @@ def note_constexpr_destroy_out_of_lifetime : Note< "destroying object '%0' whose lifetime has already ended">; def note_constexpr_unsupported_destruction : Note< "non-trivial destruction of type %0 in a constant expression is not supported">; -def note_constexpr_unsupported_tempoarary_nontrivial_dtor : Note< +def note_constexpr_unsupported_temporary_nontrivial_dtor : Note< "non-trivial destruction of lifetime-extended temporary with type %0 " "used in the result of a constant expression is not yet supported">; def note_constexpr_unsupported_unsized_array : Note< diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 65e3755efd22e..a4f96a97991ea 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -234,6 +234,12 @@ def err_seh___finally_block : Error< // Sema && AST def note_invalid_subexpr_in_const_expr : Note< "subexpression not valid in a constant expression">; +def note_constexpr_invalid_template_arg : Note< + "%select{pointer|reference}0 to %select{|subobject of }1" + "%select{type_info object|string literal|temporary object|" + "predefined '%3' variable}2 is not allowed in a template argument">; +def err_constexpr_invalid_template_arg : Error< + note_constexpr_invalid_template_arg.Text>; // Sema && Frontend let CategoryName = "Inline Assembly Issue" in { diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 5d49f41dd15ff..165cd70384440 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -69,7 +69,7 @@ def err_drv_cuda_version_unsupported : Error< "install, pass a different GPU arch with --cuda-gpu-arch, or pass " "--no-cuda-version-check.">; def warn_drv_unknown_cuda_version: Warning< - "Unknown CUDA version %0. Assuming the latest supported version %1">, + "Unknown CUDA version. %0 Assuming the latest supported version %1">, InGroup; def err_drv_cuda_host_arch : Error<"unsupported architecture '%0' for host compilation.">; def err_drv_no_sycl_libspirv : Error< @@ -223,6 +223,7 @@ def err_drv_dllexport_inlines_and_fallback : Error< def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; +def err_drv_invalid_value_with_suggestion : Error<"invalid value '%1' in '%0','%2'">; def err_drv_invalid_remap_file : Error< "invalid option '%0' not of the form ;">; def err_drv_invalid_gcc_output_type : Error< diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index cb9f2f2f5c5e4..df36366821c6c 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1135,9 +1135,12 @@ def err_pragma_file_or_compound_scope : Error< // - #pragma stdc unknown def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, InGroup; -def warn_stdc_fenv_access_not_supported : - Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, - InGroup; +// The C standard 7.6.1p2 says "The [FENV_ACCESS] pragma shall occur either +// outside external declarations or preceding all explicit declarations and +// statements inside a compound statement. +def err_pragma_stdc_fenv_access_scope : Error< + "'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of" + " a compound statement">; def warn_stdc_fenv_round_not_supported : Warning<"pragma STDC FENV_ROUND is not supported">, InGroup; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2de36ff88607d..41ed6ade6e107 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -517,6 +517,8 @@ def err_decomp_decl_inaccessible_base : Error< def err_decomp_decl_inaccessible_field : Error< "cannot decompose %select{private|protected}0 member %1 of %3">, AccessControl; +def err_decomp_decl_lambda : Error< + "cannot decompose lambda closure type">; def err_decomp_decl_anon_union_member : Error< "cannot decompose class type %0 because it has an anonymous " "%select{struct|union}1 member">; @@ -2025,8 +2027,8 @@ def err_destructor_template : Error< // C++ initialization def err_init_conversion_failed : Error< - "cannot initialize %select{a variable|a parameter|return object|" - "statement expression result|an " + "cannot initialize %select{a variable|a parameter|template parameter|" + "return object|statement expression result|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " "block element|a complex element|a lambda capture|a compound literal " @@ -2168,7 +2170,7 @@ def warn_unsequenced_mod_use : Warning< "unsequenced modification and access to %0">, InGroup; def select_initialized_entity_kind : TextSubstitution< - "%select{copying variable|copying parameter|" + "%select{copying variable|copying parameter|initializing template parameter|" "returning object|initializing statement expression result|" "throwing object|copying member subobject|copying array element|" "allocating object|copying temporary|initializing base subobject|" @@ -2899,7 +2901,7 @@ def err_attribute_sizeless_type : Error< "%0 attribute cannot be applied to sizeless type %1">; def err_attribute_argument_n_type : Error< "%0 attribute requires parameter %1 to be %select{int or bool|an integer " - "constant|a string|an identifier}2">; + "constant|a string|an identifier|a constant expression}2">; def err_attribute_argument_type : Error< "%0 attribute requires %select{int or bool|an integer " "constant|a string|an identifier}1">; @@ -4533,6 +4535,10 @@ def note_not_structural_rvalue_ref_field : Note< def note_not_structural_subobject : Note< "%0 is not a structural type because it has a " "%select{non-static data member|base class}1 of non-structural type %2">; +def warn_cxx17_compat_template_nontype_parm_type : Warning< + "non-type template parameter of type %0 is incompatible with " + "C++ standards before C++20">, + DefaultIgnore, InGroup; def warn_cxx14_compat_template_nontype_parm_auto_type : Warning< "non-type template parameters declared with %0 are incompatible with C++ " "standards before C++17">, @@ -11131,11 +11137,6 @@ def warn_sycl_pass_by_value_deprecated def warn_sycl_pass_by_reference_future : Warning<"Passing of kernel functions by reference is a SYCL 2020 extension">, InGroup, ShowInSystemHeader; -def warn_sycl_attibute_function_raw_ptr - : Warning<"SYCL 1.2.1 specification does not allow %0 attribute applied " - "to a function with a raw pointer " - "%select{return type|parameter type}1">, - InGroup, DefaultError; def warn_sycl_implicit_decl : Warning<"SYCL 1.2.1 specification requires an explicit forward " "declaration for a kernel type name; your program may not " diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index 089304e1d1e6d..8fcea2d5cbf33 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -71,6 +71,37 @@ class DirectoryEntryRef { const llvm::StringMapEntry> *Entry; }; +class FileEntry; + +/// A reference to a \c FileEntry that includes the name of the file as it was +/// accessed by the FileManager's client. +class FileEntryRef { +public: + FileEntryRef() = delete; + FileEntryRef(StringRef Name, const FileEntry &Entry) + : Name(Name), Entry(&Entry) {} + + const StringRef getName() const { return Name; } + const FileEntry &getFileEntry() const { return *Entry; } + + inline bool isValid() const; + inline off_t getSize() const; + inline unsigned getUID() const; + inline const llvm::sys::fs::UniqueID &getUniqueID() const; + inline time_t getModificationTime() const; + + friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) { + return LHS.Entry == RHS.Entry && LHS.Name == RHS.Name; + } + friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) { + return !(LHS == RHS); + } + +private: + StringRef Name; + const FileEntry *Entry; +}; + /// Cached information about one file (either on disk /// or in the virtual file system). /// @@ -126,41 +157,19 @@ class FileEntry { bool isOpenForTests() const { return File != nullptr; } }; -/// A reference to a \c FileEntry that includes the name of the file as it was -/// accessed by the FileManager's client. -class FileEntryRef { -public: - FileEntryRef() = delete; - FileEntryRef(StringRef Name, const FileEntry &Entry) - : Name(Name), Entry(&Entry) {} +bool FileEntryRef::isValid() const { return getFileEntry().isValid(); } - const StringRef getName() const { return Name; } - - bool isValid() const { return Entry->isValid(); } - - const FileEntry &getFileEntry() const { return *Entry; } - - off_t getSize() const { return Entry->getSize(); } +off_t FileEntryRef::getSize() const { return getFileEntry().getSize(); } - unsigned getUID() const { return Entry->getUID(); } +unsigned FileEntryRef::getUID() const { return getFileEntry().getUID(); } - const llvm::sys::fs::UniqueID &getUniqueID() const { - return Entry->getUniqueID(); - } +const llvm::sys::fs::UniqueID &FileEntryRef::getUniqueID() const { + return getFileEntry().getUniqueID(); +} - time_t getModificationTime() const { return Entry->getModificationTime(); } - - friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) { - return LHS.Entry == RHS.Entry && LHS.Name == RHS.Name; - } - friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) { - return !(LHS == RHS); - } - -private: - StringRef Name; - const FileEntry *Entry; -}; +time_t FileEntryRef::getModificationTime() const { + return getFileEntry().getModificationTime(); +} /// Implements support for file system lookup, file system caching, /// and directory search management. diff --git a/clang/include/clang/Basic/LLVM.h b/clang/include/clang/Basic/LLVM.h index e9bb96af972e0..02e4220510711 100644 --- a/clang/include/clang/Basic/LLVM.h +++ b/clang/include/clang/Basic/LLVM.h @@ -54,6 +54,7 @@ namespace llvm { namespace clang { // Casting operators. using llvm::isa; + using llvm::isa_and_nonnull; using llvm::cast; using llvm::dyn_cast; using llvm::dyn_cast_or_null; diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 6717c87bfd28d..bcbdce1e33e8f 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -421,13 +421,20 @@ class FPOptions { setFPContractMode(LO.getDefaultFPContractMode()); setRoundingMode(LO.getFPRoundingMode()); setFPExceptionMode(LO.getFPExceptionMode()); - setAllowFEnvAccess(LangOptions::FPM_Off); setAllowFPReassociate(LO.AllowFPReassoc); setNoHonorNaNs(LO.NoHonorNaNs); setNoHonorInfs(LO.NoHonorInfs); setNoSignedZero(LO.NoSignedZero); setAllowReciprocal(LO.AllowRecip); setAllowApproxFunc(LO.ApproxFunc); + if (getFPContractMode() == LangOptions::FPM_On && + getRoundingMode() == llvm::RoundingMode::Dynamic && + getFPExceptionMode() == LangOptions::FPE_Strict) + // If the FP settings are set to the "strict" model, then + // FENV access is set to true. (ffp-model=strict) + setAllowFEnvAccess(true); + else + setAllowFEnvAccess(LangOptions::FPM_Off); } bool allowFPContractWithinStatement() const { diff --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def index 1ae36b32fb0a9..d67cb3ff019b4 100644 --- a/clang/include/clang/Basic/OpenCLExtensions.def +++ b/clang/include/clang/Basic/OpenCLExtensions.def @@ -23,6 +23,16 @@ // core - minimum OpenCL version when the extension becomes optional core // feature or core feature. ~0U indicates not a core feature or an // optional core feature. +// +// As per The OpenCL Extension Specification, Section 1.2, in this file, an +// extension is defined if and only it either: +// * affects the OpenCL language semantics or its syntax, +// * adds built-in functions to the language. +// +// For such an extension, a preprocessor #define that matches the extension +// name must be created and a #pragma is required if and only if the +// compilation flow is impacted, e.g. due to a difference of syntax or +// semantics in the language compared to the core standard. #ifndef OPENCLEXT_INTERNAL #ifndef OPENCLEXT @@ -34,8 +44,6 @@ // OpenCL 1.0. OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) -// fprounding mode is special since it is not mentioned beyond 1.0 -OPENCLEXT_INTERNAL(cl_khr_select_fprounding_mode, 100, 110) OPENCLEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) OPENCLEXT_INTERNAL(cl_khr_fp16, 100, ~0U) OPENCLEXT_INTERNAL(cl_khr_fp64, 100, 120) @@ -45,35 +53,19 @@ OPENCLEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) OPENCLEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100, ~0U) OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_sharing, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_icd, 100, ~0U) - -// OpenCL 1.1. -OPENCLEXT_INTERNAL(cl_khr_gl_event, 110, ~0U) -OPENCLEXT_INTERNAL(cl_khr_d3d10_sharing, 110, ~0U) // EMBEDDED_PROFILE OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U) // OpenCL 1.2. -OPENCLEXT_INTERNAL(cl_khr_context_abort, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_d3d11_sharing, 120, ~0U) OPENCLEXT_INTERNAL(cl_khr_depth_images, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_dx9_media_sharing, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_image2d_from_buffer, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_initialize_memory, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_depth_images, 120, ~0U) OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_spir, 120, ~0U) // OpenCL 2.0. -OPENCLEXT_INTERNAL(cl_khr_egl_event, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_egl_image, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_terminate_context, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200, ~0U) diff --git a/clang/include/clang/Basic/PartialDiagnostic.h b/clang/include/clang/Basic/PartialDiagnostic.h index 370bc6861dd6c..9fb70bff7fee1 100644 --- a/clang/include/clang/Basic/PartialDiagnostic.h +++ b/clang/include/clang/Basic/PartialDiagnostic.h @@ -142,6 +142,7 @@ class PartialDiagnostic : public StreamingDiagnostic { } unsigned getDiagID() const { return DiagID; } + void setDiagID(unsigned ID) { DiagID = ID; } void Emit(const DiagnosticBuilder &DB) const { if (!DiagStorage) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 65c3de5a1e418..a458ef7e72a89 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -90,6 +90,35 @@ namespace SrcMgr { return CK == C_User_ModuleMap || CK == C_System_ModuleMap; } + /// Mapping of line offsets into a source file. This does not own the storage + /// for the line numbers. + class LineOffsetMapping { + public: + explicit operator bool() const { return Storage; } + unsigned size() const { + assert(Storage); + return Storage[0]; + } + ArrayRef getLines() const { + assert(Storage); + return ArrayRef(Storage + 1, Storage + 1 + size()); + } + const unsigned *begin() const { return getLines().begin(); } + const unsigned *end() const { return getLines().end(); } + const unsigned &operator[](int I) const { return getLines()[I]; } + + static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, + llvm::BumpPtrAllocator &Alloc); + + LineOffsetMapping() = default; + LineOffsetMapping(ArrayRef LineOffsets, + llvm::BumpPtrAllocator &Alloc); + + private: + /// First element is the size, followed by elements at off-by-one indexes. + unsigned *Storage = nullptr; + }; + /// One instance of this struct is kept for every file loaded or used. /// /// This object owns the MemoryBuffer object. @@ -115,14 +144,9 @@ namespace SrcMgr { /// A bump pointer allocated array of offsets for each source line. /// - /// This is lazily computed. This is owned by the SourceManager + /// This is lazily computed. The lines are owned by the SourceManager /// BumpPointerAllocator object. - unsigned *SourceLineCache = nullptr; - - /// The number of lines in this ContentCache. - /// - /// This is only valid if SourceLineCache is non-null. - unsigned NumLines = 0; + mutable LineOffsetMapping SourceLineCache; /// Indicates whether the buffer itself was provided to override /// the actual file contents. @@ -157,10 +181,8 @@ namespace SrcMgr { OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; - assert(!RHS.Buffer && RHS.SourceLineCache == nullptr && + assert(!RHS.Buffer && !RHS.SourceLineCache && "Passed ContentCache object cannot own a buffer."); - - NumLines = RHS.NumLines; } ContentCache &operator=(const ContentCache& RHS) = delete; @@ -194,9 +216,23 @@ namespace SrcMgr { /// this content cache. This is used for performance analysis. llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; - /// Get the underlying buffer, returning NULL if the buffer is not - /// yet available. - const llvm::MemoryBuffer *getRawBuffer() const { return Buffer.get(); } + /// Return the buffer, only if it has been loaded. + /// specified FileID, returning None if it's not yet loaded. + /// + /// \param FID The file ID whose contents will be returned. + llvm::Optional getBufferIfLoaded() const { + if (Buffer) + return Buffer->getMemBufferRef(); + return None; + } + + /// Return a StringRef to the source buffer data, only if it has already + /// been loaded. + llvm::Optional getBufferDataIfLoaded() const { + if (Buffer) + return Buffer->getBuffer(); + return None; + } /// Set the buffer. void setBuffer(std::unique_ptr B) { @@ -207,10 +243,10 @@ namespace SrcMgr { /// Set the buffer to one that's not owned (or to nullptr). /// /// \pre Buffer cannot already be set. - void setUnownedBuffer(const llvm::MemoryBuffer *B) { + void setUnownedBuffer(llvm::Optional B) { assert(!Buffer && "Expected to be called right after construction"); if (B) - setBuffer(llvm::MemoryBuffer::getMemBuffer(B->getMemBufferRef())); + setBuffer(llvm::MemoryBuffer::getMemBuffer(*B)); } // If BufStr has an invalid BOM, returns the BOM name; otherwise, returns @@ -261,13 +297,13 @@ namespace SrcMgr { public: /// Return a FileInfo object. - static FileInfo get(SourceLocation IL, const ContentCache *Con, + static FileInfo get(SourceLocation IL, const ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename) { FileInfo X; X.IncludeLoc = IL.getRawEncoding(); X.NumCreatedFIDs = 0; X.HasLineDirectives = false; - X.ContentAndKind.setPointer(Con); + X.ContentAndKind.setPointer(&Con); X.ContentAndKind.setInt(FileCharacter); X.Filename = Filename; return X; @@ -277,8 +313,8 @@ namespace SrcMgr { return SourceLocation::getFromRawEncoding(IncludeLoc); } - const ContentCache *getContentCache() const { - return ContentAndKind.getPointer(); + const ContentCache &getContentCache() const { + return *ContentAndKind.getPointer(); } /// Return whether this is a system header or not. @@ -683,7 +719,7 @@ class SourceManager : public RefCountedBase { /// These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. mutable FileID LastLineNoFileIDQuery; - mutable SrcMgr::ContentCache *LastLineNoContentCache; + mutable const SrcMgr::ContentCache *LastLineNoContentCache; mutable unsigned LastLineNoFilePos; mutable unsigned LastLineNoResult; @@ -800,7 +836,7 @@ class SourceManager : public RefCountedBase { /// Returns true when the given FileEntry corresponds to the main file. /// /// The main file should be set prior to calling this function. - bool isMainFile(FileEntryRef SourceFile); + bool isMainFile(const FileEntry &SourceFile); /// Set the file ID for the precompiled preamble. void setPreambleFileID(FileID Preamble) { @@ -958,13 +994,10 @@ class SourceManager : public RefCountedBase { /// If there is an error opening this buffer the first time, return None. llvm::Optional getBufferOrNone(FileID FID, SourceLocation Loc = SourceLocation()) const { - bool MyInvalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); - if (MyInvalid || !Entry.isFile()) - return None; - - return Entry.getFile().getContentCache()->getBufferOrNone( - Diag, getFileManager(), Loc); + if (auto *Entry = getSLocEntryForFile(FID)) + return Entry->getFile().getContentCache().getBufferOrNone( + Diag, getFileManager(), Loc); + return None; } /// Return the buffer for the specified FileID. @@ -980,27 +1013,21 @@ class SourceManager : public RefCountedBase { /// Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { - bool MyInvalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); - if (MyInvalid || !Entry.isFile()) - return nullptr; - - const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache(); - if (!Content) - return nullptr; - return Content->OrigEntry; + if (auto *Entry = getSLocEntryForFile(FID)) + return Entry->getFile().getContentCache().OrigEntry; + return nullptr; } - /// Returns the FileEntryRef for the provided FileID. - Optional getFileEntryRefForID(FileID FID) const; + /// Returns the filename for the provided FileID, unless it's a built-in + /// buffer that's not represented by a filename. + /// + /// Returns None for non-files and built-in files. + Optional getNonBuiltinFilenameForID(FileID FID) const; /// Returns the FileEntry record for the provided SLocEntry. const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const { - const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache(); - if (!Content) - return nullptr; - return Content->OrigEntry; + return sloc.getFile().getContentCache().OrigEntry; } /// Return a StringRef to the source buffer data for the @@ -1025,25 +1052,20 @@ class SourceManager : public RefCountedBase { /// Get the number of FileIDs (files and macros) that were created /// during preprocessing of \p FID, including it. unsigned getNumCreatedFIDsForFileID(FileID FID) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid || !Entry.isFile()) - return 0; - - return Entry.getFile().NumCreatedFIDs; + if (auto *Entry = getSLocEntryForFile(FID)) + return Entry->getFile().NumCreatedFIDs; + return 0; } /// Set the number of FileIDs (files and macros) that were created /// during preprocessing of \p FID, including it. void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs, bool Force = false) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid || !Entry.isFile()) + auto *Entry = getSLocEntryForFile(FID); + if (!Entry) return; - - assert((Force || Entry.getFile().NumCreatedFIDs == 0) && "Already set!"); - const_cast(Entry.getFile()).NumCreatedFIDs = NumFIDs; + assert((Force || Entry->getFile().NumCreatedFIDs == 0) && "Already set!"); + const_cast(Entry->getFile()).NumCreatedFIDs = NumFIDs; } //===--------------------------------------------------------------------===// @@ -1072,36 +1094,26 @@ class SourceManager : public RefCountedBase { /// Return the source location corresponding to the first byte of /// the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid || !Entry.isFile()) - return SourceLocation(); - - unsigned FileOffset = Entry.getOffset(); - return SourceLocation::getFileLoc(FileOffset); + if (auto *Entry = getSLocEntryForFile(FID)) + return SourceLocation::getFileLoc(Entry->getOffset()); + return SourceLocation(); } /// Return the source location corresponding to the last byte of the /// specified file. SourceLocation getLocForEndOfFile(FileID FID) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid || !Entry.isFile()) - return SourceLocation(); - - unsigned FileOffset = Entry.getOffset(); - return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID)); + if (auto *Entry = getSLocEntryForFile(FID)) + return SourceLocation::getFileLoc(Entry->getOffset() + + getFileIDSize(FID)); + return SourceLocation(); } /// Returns the include location if \p FID is a \#include'd file /// otherwise it returns an invalid location. SourceLocation getIncludeLoc(FileID FID) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid || !Entry.isFile()) - return SourceLocation(); - - return Entry.getFile().getIncludeLoc(); + if (auto *Entry = getSLocEntryForFile(FID)) + return Entry->getFile().getIncludeLoc(); + return SourceLocation(); } // Returns the import location if the given source location is @@ -1186,14 +1198,13 @@ class SourceManager : public RefCountedBase { /// Form a SourceLocation from a FileID and Offset pair. SourceLocation getComposedLoc(FileID FID, unsigned Offset) const { - bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); - if (Invalid) + auto *Entry = getSLocEntryOrNull(FID); + if (!Entry) return SourceLocation(); - unsigned GlobalOffset = Entry.getOffset() + Offset; - return Entry.isFile() ? SourceLocation::getFileLoc(GlobalOffset) - : SourceLocation::getMacroLoc(GlobalOffset); + unsigned GlobalOffset = Entry->getOffset() + Offset; + return Entry->isFile() ? SourceLocation::getFileLoc(GlobalOffset) + : SourceLocation::getMacroLoc(GlobalOffset); } /// Decompose the specified location into a raw FileID + Offset pair. @@ -1202,11 +1213,10 @@ class SourceManager : public RefCountedBase { /// start of the buffer of the location. std::pair getDecomposedLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); - bool Invalid = false; - const SrcMgr::SLocEntry &E = getSLocEntry(FID, &Invalid); - if (Invalid) + auto *Entry = getSLocEntryOrNull(FID); + if (!Entry) return std::make_pair(FileID(), 0); - return std::make_pair(FID, Loc.getOffset()-E.getOffset()); + return std::make_pair(FID, Loc.getOffset() - Entry->getOffset()); } /// Decompose the specified location into a raw FileID + Offset pair. @@ -1216,9 +1226,8 @@ class SourceManager : public RefCountedBase { std::pair getDecomposedExpansionLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); - bool Invalid = false; - const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid); - if (Invalid) + auto *E = getSLocEntryOrNull(FID); + if (!E) return std::make_pair(FileID(), 0); unsigned Offset = Loc.getOffset()-E->getOffset(); @@ -1235,9 +1244,8 @@ class SourceManager : public RefCountedBase { std::pair getDecomposedSpellingLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); - bool Invalid = false; - const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid); - if (Invalid) + auto *E = getSLocEntryOrNull(FID); + if (!E) return std::make_pair(FileID(), 0); unsigned Offset = Loc.getOffset()-E->getOffset(); @@ -1735,6 +1743,19 @@ class SourceManager : public RefCountedBase { const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; + const SrcMgr::SLocEntry *getSLocEntryOrNull(FileID FID) const { + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + return Invalid ? nullptr : &Entry; + } + + const SrcMgr::SLocEntry *getSLocEntryForFile(FileID FID) const { + if (auto *Entry = getSLocEntryOrNull(FID)) + if (Entry->isFile()) + return Entry; + return nullptr; + } + /// Get the entry with the given unwrapped FileID. /// Invalid will not be modified for Local IDs. const SrcMgr::SLocEntry &getSLocEntryByID(int ID, @@ -1790,10 +1811,10 @@ class SourceManager : public RefCountedBase { /// /// This works regardless of whether the ContentCache corresponds to a /// file or some other input source. - FileID createFileID(const SrcMgr::ContentCache *File, StringRef Filename, - SourceLocation IncludePos, - SrcMgr::CharacteristicKind DirCharacter, int LoadedID, - unsigned LoadedOffset); + FileID createFileIDImpl(const SrcMgr::ContentCache &File, StringRef Filename, + SourceLocation IncludePos, + SrcMgr::CharacteristicKind DirCharacter, int LoadedID, + unsigned LoadedOffset); const SrcMgr::ContentCache * getOrCreateContentCache(const FileEntry *SourceFile, diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 7253b5ea9abed..26dc6eacb2041 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -581,8 +581,9 @@ class TargetInfo : public virtual TransferrableTargetInfo, /// Determine whether constrained floating point is supported on this target. virtual bool hasStrictFP() const { return HasStrictFP; } - /// Return the alignment that is suitable for storing any - /// object with a fundamental alignment requirement. + /// Return the alignment that is the largest alignment ever used for any + /// scalar/SIMD data type on the target machine you are compiling for + /// (including types with an extended alignment requirement). unsigned getSuitableAlign() const { return SuitableAlign; } /// Return the default alignment for __attribute__((aligned)) on diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td index 25daae2a0a25d..8106f9a5a9def 100644 --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -406,7 +406,7 @@ def vabdq: Intrinsic { + bit wantXVariant = 1> { defm "" : IntrinsicMX< Vector, (args Vector:$a, Vector:$b, Predicate:$pred), !con((IRInt $a, $b), @@ -415,7 +415,7 @@ multiclass VectorVectorArithmetic { + bit wantXVariant = 1> { defm "" : IntrinsicMXNameOverride< Vector, (args Vector:$a, unpromoted:$b, Predicate:$pred), !con((IRInt $a, (splat $b)), @@ -451,7 +451,7 @@ let params = T.Usual in { } multiclass DblVectorVectorArithmetic { + bit wantXVariant = 1> { defm "" : IntrinsicMX< DblVector, (args Vector:$a, Vector:$b, DblPredicate:$pred), !con((IRInt $a, $b), @@ -460,7 +460,7 @@ multiclass DblVectorVectorArithmetic { + bit wantXVariant = 1> { defm "" : IntrinsicMXNameOverride< DblVector, (args Vector:$a, unpromoted:$b, DblPredicate:$pred), !con((IRInt $a, (splat $b)), @@ -545,8 +545,8 @@ multiclass Reduction basetypes, defvar intArgsUnpred = !con(intArgsBase, !if(needSign, (? (unsignedflag Scalar)), (?))); defvar intArgsPred = !con(intArgsUnpred, (? $pred)); - defvar intUnpred = !setop(intArgsUnpred, IRInt); - defvar intPred = !setop(intArgsPred, IRInt< + defvar intUnpred = !setdagop(intArgsUnpred, IRInt); + defvar intPred = !setdagop(intArgsPred, IRInt< basename#"_predicated", !listconcat(basetypes, [Predicate])>); def "": Intrinsic< diff --git a/clang/include/clang/Basic/arm_mve_defs.td b/clang/include/clang/Basic/arm_mve_defs.td index 4038a18027f8c..1a090c08cc853 100644 --- a/clang/include/clang/Basic/arm_mve_defs.td +++ b/clang/include/clang/Basic/arm_mve_defs.td @@ -519,7 +519,7 @@ class NameOverride { // polymorph differently (typically because the type of the inactive // parameter can be used as a disambiguator if it's present). multiclass IntrinsicMX { @@ -532,7 +532,7 @@ multiclass IntrinsicMX) in { + if wantXVariant then { // The _x variant leaves off that parameter, and simply uses an // undef value of the same type. @@ -546,7 +546,7 @@ multiclass IntrinsicMX { @@ -556,7 +556,7 @@ multiclass IntrinsicMXNameOverride) in { + if wantXVariant then { def "_x" # nameSuffix: Intrinsic, NameOverride { diff --git a/clang/include/clang/Driver/Options.h b/clang/include/clang/Driver/Options.h index 06dd3652be940..ae188cec93c20 100644 --- a/clang/include/clang/Driver/Options.h +++ b/clang/include/clang/Driver/Options.h @@ -36,7 +36,8 @@ enum ClangFlags { LinkOption = (1 << 13), FlangOption = (1 << 14), FC1Option = (1 << 15), - Ignored = (1 << 16), + FlangOnlyOption = (1 << 16), + Ignored = (1 << 17), }; enum ID { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index b77b6088ba102..02b9e54966a90 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -60,6 +60,10 @@ def LinkOption : OptionFlag; // flang mode. def FlangOption : OptionFlag; +// FlangOnlyOption - This option should only be used by Flang (i.e. it is not +// available for Clang) +def FlangOnlyOption : OptionFlag; + // FC1Option - This option should be accepted by flang -fc1. def FC1Option : OptionFlag; @@ -1602,7 +1606,7 @@ def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-m Group, Flags<[CC1Option]>, HelpText<"Disables an experimental new pass manager in LLVM.">; def fveclib : Joined<["-"], "fveclib=">, Group, Flags<[CC1Option]>, - HelpText<"Use the given vector functions library">, Values<"Accelerate,MASSV,SVML,none">; + HelpText<"Use the given vector functions library">, Values<"Accelerate,libmvec,MASSV,SVML,none">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, Alias, AliasArgs<["none"]>; def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group, @@ -2194,8 +2198,8 @@ def gno_embed_source : Flag<["-"], "gno-embed-source">, Group, Flags<[DriverOption]>, HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; -def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption, FC1Option, FlangOption]>, - HelpText<"Display available options">; +def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption, FC1Option, + FlangOption]>, HelpText<"Display available options">; def ibuiltininc : Flag<["-"], "ibuiltininc">, HelpText<"Enable builtin #include directories even when -nostdinc is used " "before or after -ibuiltininc. " @@ -2670,6 +2674,12 @@ def mrecip : Flag<["-"], "mrecip">, Group; def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group, Flags<[CC1Option]>; def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group, Flags<[CC1Option]>, HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">; +def mstack_protector_guard_EQ : Joined<["-"], "mstack-protector-guard=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given guard (global, tls) for addressing the stack-protector guard">; +def mstack_protector_guard_offset_EQ : Joined<["-"], "mstack-protector-guard-offset=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given offset for addressing the stack-protector guard">; +def mstack_protector_guard_reg_EQ : Joined<["-"], "mstack-protector-guard-reg=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given reg for addressing the stack-protector guard">; def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group, Flags<[CC1Option]>, HelpText<"Use copy relocations support for PIE builds">; @@ -2871,7 +2881,8 @@ def nostdlibxx : Flag<["-"], "nostdlib++">; def nolibsycl : Flag<["-"], "nolibsycl">, Flags<[DriverOption, CoreOption]>, HelpText<"Do not link SYCL runtime library">; def object : Flag<["-"], "object">; -def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>, +def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, + CC1Option, CC1AsOption, FC1Option, FlangOption]>, HelpText<"Write output to ">, MetaVarName<"">; def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">; def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>; @@ -3381,6 +3392,8 @@ def mtbm : Flag<["-"], "mtbm">, Group; def mno_tbm : Flag<["-"], "mno-tbm">, Group; def mtsxldtrk : Flag<["-"], "mtsxldtrk">, Group; def mno_tsxldtrk : Flag<["-"], "mno-tsxldtrk">, Group; +def muintr : Flag<["-"], "muintr">, Group; +def mno_uintr : Flag<["-"], "mno-uintr">, Group; def mvaes : Flag<["-"], "mvaes">, Group; def mno_vaes : Flag<["-"], "mno-vaes">, Group; def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group; @@ -3626,6 +3639,12 @@ def fno_sycl_device_lib_EQ : CommaJoined<["-"], "fno-sycl-device-lib=">, Group; +//===----------------------------------------------------------------------===// +// FlangOption and FC1 Options +//===----------------------------------------------------------------------===// +def test_io : Flag<["-"], "test-io">, Flags<[HelpHidden, FlangOption, FC1Option, FlangOnlyOption]>, Group, + HelpText<"Run the InputOuputTest action. Use for development and testing only.">; + //===----------------------------------------------------------------------===// // CC1 Options //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index ca9e0a198cb91..6976e7c95c8b2 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -55,6 +55,9 @@ class alignas(8) InitializedEntity { /// The entity being initialized is a function parameter. EK_Parameter, + /// The entity being initialized is a non-type template parameter. + EK_TemplateParameter, + /// The entity being initialized is the result of a function call. EK_Result, @@ -175,7 +178,8 @@ class alignas(8) InitializedEntity { }; union { - /// When Kind == EK_Variable, EK_Member or EK_Binding, the variable. + /// When Kind == EK_Variable, EK_Member, EK_Binding, or + /// EK_TemplateParameter, the variable, binding, or template parameter. VD Variable; /// When Kind == EK_RelatedResult, the ObjectiveC method where @@ -281,6 +285,17 @@ class alignas(8) InitializedEntity { return Entity; } + /// Create the initialization entity for a template parameter. + static InitializedEntity + InitializeTemplateParameter(QualType T, NonTypeTemplateParmDecl *Param) { + InitializedEntity Entity; + Entity.Kind = EK_TemplateParameter; + Entity.Type = T; + Entity.Parent = nullptr; + Entity.Variable = {Param, false, false}; + return Entity; + } + /// Create the initialization entity for the result of a function. static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type, bool NRVO) { @@ -441,6 +456,10 @@ class alignas(8) InitializedEntity { getKind() == EK_Parameter_CF_Audited); } + bool isParamOrTemplateParamKind() const { + return isParameterKind() || getKind() == EK_TemplateParameter; + } + /// Determine whether this initialization consumes the /// parameter. bool isParameterConsumed() const { diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 45b0f85857f6d..43c21faaece9f 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -1023,7 +1023,8 @@ enum AttributeArgumentNType { AANT_ArgumentIntOrBool, AANT_ArgumentIntegerConstant, AANT_ArgumentString, - AANT_ArgumentIdentifier + AANT_ArgumentIdentifier, + AANT_ArgumentConstantExpr, }; /// These constants match the enumerated choices of @@ -1058,6 +1059,31 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, return DB; } +/// AttributeCommonInfo has a non-explicit constructor which takes an +/// SourceRange as its only argument, this constructor has many uses so making +/// it explicit is hard. This constructor causes ambiguity with +/// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R). +/// We use SFINAE to disable any conversion and remove any ambiguity. +template ::value, int> = 0> +inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, + const ACI &CI) { + DB.AddTaggedVal(reinterpret_cast(CI.getAttrName()), + DiagnosticsEngine::ak_identifierinfo); + return DB; +} + +template ::value, int> = 0> +inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, + const ACI* CI) { + DB.AddTaggedVal(reinterpret_cast(CI->getAttrName()), + DiagnosticsEngine::ak_identifierinfo); + return DB; +} + } // namespace clang #endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index f0f9cb9e40ae0..ff2a20923415e 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -127,6 +127,9 @@ class FunctionScopeInfo { /// Whether there is a fallthrough statement in this function. bool HasFallthroughStmt : 1; + /// Whether this function uses constrained floating point intrinsics + bool UsesFPIntrin : 1; + /// Whether we make reference to a declaration that could be /// unavailable. bool HasPotentialAvailabilityViolations : 1; @@ -369,7 +372,8 @@ class FunctionScopeInfo { : Kind(SK_Function), HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), - HasFallthroughStmt(false), HasPotentialAvailabilityViolations(false), + HasFallthroughStmt(false), UsesFPIntrin(false), + HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true), @@ -431,6 +435,10 @@ class FunctionScopeInfo { HasFallthroughStmt = true; } + void setUsesFPIntrin() { + UsesFPIntrin = true; + } + void setHasCXXTry(SourceLocation TryLoc) { setHasBranchProtectedScope(); FirstCXXTryLoc = TryLoc; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b1efcf73cf584..c80fd20a58583 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3503,7 +3503,8 @@ class Sema final { ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, - APValue &Value, CCEKind CCE); + APValue &Value, CCEKind CCE, + NamedDecl *Dest = nullptr); /// Abstract base class used to perform a contextual implicit /// conversion from an expression to any type passing a filter. @@ -4022,7 +4023,7 @@ class Sema final { /// The lookup found an overload set of literal operator templates, /// which expect the character type and characters of the spelling of the /// string literal token to be passed as template arguments. - LOLR_StringTemplate + LOLR_StringTemplatePack, }; SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, @@ -4130,12 +4131,11 @@ class Sema final { CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id); - LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, - ArrayRef ArgTys, - bool AllowRaw, - bool AllowTemplate, - bool AllowStringTemplate, - bool DiagnoseMissing); + LiteralOperatorLookupResult + LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys, + bool AllowRaw, bool AllowTemplate, + bool AllowStringTemplate, bool DiagnoseMissing, + StringLiteral *StringLit = nullptr); bool isKnownName(StringRef name); /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs. @@ -4612,6 +4612,7 @@ class Sema final { bool HasLeadingEmptyMacro = false); void ActOnStartOfCompoundStmt(bool IsStmtExpr); + void ActOnAfterCompoundStatementLeadingPragmas(); void ActOnFinishOfCompoundStmt(); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef Elts, bool isStmtExpr); @@ -10143,6 +10144,10 @@ class Sema final { /// declaration. void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E); + /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D. + void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Annot, MutableArrayRef Args); + /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular /// declaration. void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 726c383ade807..52ddd57492025 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1286,6 +1286,9 @@ class TypeIdx { /// A MSGuidDecl record. DECL_MS_GUID, + /// A TemplateParamObjectDecl record. + DECL_TEMPLATE_PARAM_OBJECT, + /// A VarDecl record. DECL_VAR, diff --git a/clang/include/clang/Tooling/Transformer/RewriteRule.h b/clang/include/clang/Tooling/Transformer/RewriteRule.h index 4bdcc8d5c3296..13d0edaf11b37 100644 --- a/clang/include/clang/Tooling/Transformer/RewriteRule.h +++ b/clang/include/clang/Tooling/Transformer/RewriteRule.h @@ -107,7 +107,7 @@ struct ASTEdit { TextGenerator Replacement; TextGenerator Note; // Not all transformations will want or need to attach metadata and therefore - // should not be requierd to do so. + // should not be required to do so. AnyGenerator Metadata = [](const ast_matchers::MatchFinder::MatchResult &) -> llvm::Expected { return llvm::Expected(llvm::Any()); @@ -131,6 +131,11 @@ EditGenerator editList(llvm::SmallVector Edits); /// Generates no edits. inline EditGenerator noEdits() { return editList({}); } +/// Generates a single, no-op edit anchored at the start location of the +/// specified range. A `noopEdit` may be preferred over `noEdits` to associate a +/// diagnostic `Explanation` with the rule. +EditGenerator noopEdit(RangeSelector Anchor); + /// Version of `ifBound` specialized to `ASTEdit`. inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit, ASTEdit FalseEdit) { diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 8d402ee8e3dca..53aa09fa9b364 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -414,7 +414,18 @@ void APValue::swap(APValue &RHS) { std::swap(Data, RHS.Data); } +/// Profile the value of an APInt, excluding its bit-width. +static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) { + for (unsigned I = 0, N = V.getBitWidth(); I < N; I += 32) + ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I)); +} + void APValue::Profile(llvm::FoldingSetNodeID &ID) const { + // Note that our profiling assumes that only APValues of the same type are + // ever compared. As a result, we don't consider collisions that could only + // happen if the types are different. (For example, structs with different + // numbers of members could profile the same.) + ID.AddInteger(Kind); switch (Kind) { @@ -428,25 +439,22 @@ void APValue::Profile(llvm::FoldingSetNodeID &ID) const { return; case Struct: - ID.AddInteger(getStructNumBases()); for (unsigned I = 0, N = getStructNumBases(); I != N; ++I) getStructBase(I).Profile(ID); - ID.AddInteger(getStructNumFields()); for (unsigned I = 0, N = getStructNumFields(); I != N; ++I) getStructField(I).Profile(ID); return; case Union: if (!getUnionField()) { - ID.AddPointer(nullptr); + ID.AddInteger(0); return; } - ID.AddPointer(getUnionField()->getCanonicalDecl()); + ID.AddInteger(getUnionField()->getFieldIndex() + 1); getUnionValue().Profile(ID); return; case Array: { - ID.AddInteger(getArraySize()); if (getArraySize() == 0) return; @@ -502,46 +510,46 @@ void APValue::Profile(llvm::FoldingSetNodeID &ID) const { } case Vector: - ID.AddInteger(getVectorLength()); for (unsigned I = 0, N = getVectorLength(); I != N; ++I) getVectorElt(I).Profile(ID); return; case Int: - // We don't need to include the sign bit; it's implied by the type. - getInt().APInt::Profile(ID); + profileIntValue(ID, getInt()); return; case Float: - getFloat().Profile(ID); + profileIntValue(ID, getFloat().bitcastToAPInt()); return; case FixedPoint: - // We don't need to include the fixed-point semantics; they're - // implied by the type. - getFixedPoint().getValue().APInt::Profile(ID); + profileIntValue(ID, getFixedPoint().getValue()); return; case ComplexFloat: - getComplexFloatReal().Profile(ID); - getComplexFloatImag().Profile(ID); + profileIntValue(ID, getComplexFloatReal().bitcastToAPInt()); + profileIntValue(ID, getComplexFloatImag().bitcastToAPInt()); return; case ComplexInt: - getComplexIntReal().APInt::Profile(ID); - getComplexIntImag().APInt::Profile(ID); + profileIntValue(ID, getComplexIntReal()); + profileIntValue(ID, getComplexIntImag()); return; case LValue: getLValueBase().Profile(ID); ID.AddInteger(getLValueOffset().getQuantity()); - ID.AddInteger(isNullPointer()); - ID.AddInteger(isLValueOnePastTheEnd()); - // For uniqueness, we only need to profile the entries corresponding - // to union members, but we don't have the type here so we don't know - // how to interpret the entries. - for (LValuePathEntry E : getLValuePath()) - E.Profile(ID); + ID.AddInteger((isNullPointer() ? 1 : 0) | + (isLValueOnePastTheEnd() ? 2 : 0) | + (hasLValuePath() ? 4 : 0)); + if (hasLValuePath()) { + ID.AddInteger(getLValuePath().size()); + // For uniqueness, we only need to profile the entries corresponding + // to union members, but we don't have the type here so we don't know + // how to interpret the entries. + for (LValuePathEntry E : getLValuePath()) + E.Profile(ID); + } return; case MemberPointer: @@ -882,17 +890,33 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, LVal.IsNullPtr = IsNullPtr; } -void APValue::setLValue(LValueBase B, const CharUnits &O, - ArrayRef Path, bool IsOnePastTheEnd, - bool IsNullPtr) { +MutableArrayRef +APValue::setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool IsOnePastTheEnd, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data.buffer); + LV &LVal = *((LV *)(char *)Data.buffer); LVal.Base = B; LVal.IsOnePastTheEnd = IsOnePastTheEnd; LVal.Offset = O; - LVal.resizePath(Path.size()); - memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); LVal.IsNullPtr = IsNullPtr; + LVal.resizePath(Size); + return {LVal.getPath(), Size}; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef Path, bool IsOnePastTheEnd, + bool IsNullPtr) { + MutableArrayRef InternalPath = + setLValueUninit(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr); + memcpy(InternalPath.data(), Path.data(), + Path.size() * sizeof(LValuePathEntry)); +} + +void APValue::setUnion(const FieldDecl *Field, const APValue &Value) { + assert(isUnion() && "Invalid accessor"); + ((UnionData *)(char *)Data.buffer)->Field = + Field ? Field->getCanonicalDecl() : nullptr; + *((UnionData*)(char*)Data.buffer)->Value = Value; } const ValueDecl *APValue::getMemberPointerDecl() const { @@ -929,15 +953,27 @@ void APValue::MakeArray(unsigned InitElts, unsigned Size) { Kind = Array; } -void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) { +MutableArrayRef +setLValueUninit(APValue::LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + +MutableArrayRef +APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size) { assert(isAbsent() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; + MemberPointerData *MPD = new ((void *)(char *)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer( Member ? cast(Member->getCanonicalDecl()) : nullptr); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); - MPD->resizePath(Path.size()); + MPD->resizePath(Size); + return {MPD->getPath(), MPD->PathLength}; +} + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef Path) { + MutableArrayRef InternalPath = + setMemberPointerUninit(Member, IsDerivedMember, Path.size()); for (unsigned I = 0; I != Path.size(); ++I) - MPD->getPath()[I] = Path[I]->getCanonicalDecl(); + InternalPath[I] = Path[I]->getCanonicalDecl(); } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2ebc14d6c62c2..1a6a8e77f722b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1005,9 +1005,6 @@ ASTContext::~ASTContext() { for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); - - for (APValue *Value : APValueCleanups) - Value->~APValue(); } void ASTContext::setTraversalScope(const std::vector &TopLevelDecls) { @@ -4885,9 +4882,16 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { Arg = TemplateArgument(ArgType); } else if (auto *NTTP = dyn_cast(Param)) { + QualType T = + NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this); + // For class NTTPs, ensure we include the 'const' so the type matches that + // of a real template argument. + // FIXME: It would be more faithful to model this as something like an + // lvalue-to-rvalue conversion applied to a const-qualified lvalue. + if (T->isRecordType()) + T.addConst(); Expr *E = new (*this) DeclRefExpr( - *this, NTTP, /*enclosing*/ false, - NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this), + *this, NTTP, /*enclosing*/ false, T, Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); if (NTTP->isParameterPack()) @@ -11006,6 +11010,27 @@ ASTContext::getMSGuidDecl(MSGuidDecl::Parts Parts) const { return New; } +TemplateParamObjectDecl * +ASTContext::getTemplateParamObjectDecl(QualType T, const APValue &V) const { + assert(T->isRecordType() && "template param object of unexpected type"); + + // C++ [temp.param]p8: + // [...] a static storage duration object of type 'const T' [...] + T.addConst(); + + llvm::FoldingSetNodeID ID; + TemplateParamObjectDecl::Profile(ID, T, V); + + void *InsertPos; + if (TemplateParamObjectDecl *Existing = + TemplateParamObjectDecls.FindNodeOrInsertPos(ID, InsertPos)) + return Existing; + + TemplateParamObjectDecl *New = TemplateParamObjectDecl::Create(*this, T, V); + TemplateParamObjectDecls.InsertNode(New, InsertPos); + return New; +} + bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { const llvm::Triple &T = getTargetInfo().getTriple(); if (!T.isOSDarwin()) diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 99ce46e83123e..2bc731717b982 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -1834,7 +1834,14 @@ class TemplateDiff { if (VD) { if (AddressOf) OS << "&"; - OS << VD->getName(); + else if (auto *TPO = dyn_cast(VD)) { + // FIXME: Diffing the APValue would be neat. + // FIXME: Suppress this and use the full name of the declaration if the + // parameter is a pointer or reference. + TPO->printAsInit(OS); + return; + } + VD->printName(OS); return; } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 100eefa5743c2..e58538fff51e8 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -397,6 +397,7 @@ namespace clang { Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); Expected ImportCastPath(CastExpr *E); + Expected ImportAPValue(const APValue &FromValue); using Designator = DesignatedInitExpr::Designator; @@ -6698,18 +6699,11 @@ ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); + auto ToResult = importChecked(Err, E->getAPValueResult()); if (Err) return std::move(Err); - // TODO : Handle APValue::ValueKind that require importing. - - APValue::ValueKind Kind = E->getResultAPValueKind(); - if (Kind == APValue::Int || Kind == APValue::Float || - Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || - Kind == APValue::ComplexInt) - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, - E->getAPValueResult()); - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult); } ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Error Err = Error::success(); @@ -7871,7 +7865,8 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( return std::move(Err); return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( - ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement); + ToType, E->getValueKind(), ToExprLoc, ToParameter, + E->isReferenceParameter(), ToReplacement); } ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -8665,7 +8660,7 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { } ToID = ToSM.getFileID(MLoc); } else { - const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); + const SrcMgr::ContentCache *Cache = &FromSLoc.getFile().getContentCache(); if (!IsBuiltin && !Cache->BufferOverridden) { // Include location of this file. @@ -8810,6 +8805,11 @@ ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { return Imported; } +llvm::Expected ASTImporter::Import(const APValue &FromValue) { + ASTNodeImporter Importer(*this); + return Importer.ImportAPValue(FromValue); +} + Error ASTImporter::ImportDefinition(Decl *From) { ExpectedDecl ToOrErr = Import(From); if (!ToOrErr) @@ -8940,6 +8940,172 @@ Expected ASTImporter::Import(Selector FromSel) { return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data()); } +llvm::Expected +ASTNodeImporter::ImportAPValue(const APValue &FromValue) { + APValue Result; + llvm::Error Err = llvm::Error::success(); + auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) { + for (unsigned Idx = 0; Idx < Size; Idx++) { + APValue Tmp = importChecked(Err, From[Idx]); + To[Idx] = Tmp; + } + }; + switch (FromValue.getKind()) { + case APValue::None: + case APValue::Indeterminate: + case APValue::Int: + case APValue::Float: + case APValue::FixedPoint: + case APValue::ComplexInt: + case APValue::ComplexFloat: + Result = FromValue; + break; + case APValue::Vector: { + Result.MakeVector(); + MutableArrayRef Elts = + Result.setVectorUninit(FromValue.getVectorLength()); + ImportLoop( + ((const APValue::Vec *)(const char *)FromValue.Data.buffer)->Elts, + Elts.data(), FromValue.getVectorLength()); + break; + } + case APValue::Array: + Result.MakeArray(FromValue.getArrayInitializedElts(), + FromValue.getArraySize()); + ImportLoop( + ((const APValue::Arr *)(const char *)FromValue.Data.buffer)->Elts, + ((const APValue::Arr *)(const char *)Result.Data.buffer)->Elts, + FromValue.getArrayInitializedElts()); + break; + case APValue::Struct: + Result.MakeStruct(FromValue.getStructNumBases(), + FromValue.getStructNumFields()); + ImportLoop( + ((const APValue::StructData *)(const char *)FromValue.Data.buffer) + ->Elts, + ((const APValue::StructData *)(const char *)Result.Data.buffer)->Elts, + FromValue.getStructNumBases() + FromValue.getStructNumFields()); + break; + case APValue::Union: { + Result.MakeUnion(); + const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField()); + APValue ImpValue = importChecked(Err, FromValue.getUnionValue()); + if (Err) + return std::move(Err); + Result.setUnion(cast(ImpFDecl), ImpValue); + break; + } + case APValue::AddrLabelDiff: { + Result.MakeAddrLabelDiff(); + const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS()); + const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS()); + if (Err) + return std::move(Err); + Result.setAddrLabelDiff(cast(ImpLHS), + cast(ImpRHS)); + break; + } + case APValue::MemberPointer: { + const Decl *ImpMemPtrDecl = + importChecked(Err, FromValue.getMemberPointerDecl()); + if (Err) + return std::move(Err); + MutableArrayRef ToPath = + Result.setMemberPointerUninit( + cast(ImpMemPtrDecl), + FromValue.isMemberPointerToDerivedMember(), + FromValue.getMemberPointerPath().size()); + llvm::ArrayRef FromPath = + Result.getMemberPointerPath(); + for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size(); + Idx++) { + const Decl *ImpDecl = importChecked(Err, FromPath[Idx]); + if (Err) + return std::move(Err); + ToPath[Idx] = cast(ImpDecl->getCanonicalDecl()); + } + break; + } + case APValue::LValue: + APValue::LValueBase Base; + QualType FromElemTy; + if (FromValue.getLValueBase()) { + assert(!FromValue.getLValueBase().is() && + "in C++20 dynamic allocation are transient so they shouldn't " + "appear in the AST"); + if (!FromValue.getLValueBase().is()) { + if (const auto *E = + FromValue.getLValueBase().dyn_cast()) { + FromElemTy = E->getType(); + const Expr *ImpExpr = importChecked(Err, E); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(ImpExpr, + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } else { + FromElemTy = + FromValue.getLValueBase().get()->getType(); + const Decl *ImpDecl = importChecked( + Err, FromValue.getLValueBase().get()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(cast(ImpDecl), + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } + } else { + FromElemTy = FromValue.getLValueBase().getTypeInfoType(); + QualType ImpTypeInfo = importChecked( + Err, + QualType(FromValue.getLValueBase().get().getType(), + 0)); + QualType ImpType = + importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase::getTypeInfo( + TypeInfoLValue(ImpTypeInfo.getTypePtr()), ImpType); + } + } + CharUnits Offset = FromValue.getLValueOffset(); + unsigned PathLength = FromValue.getLValuePath().size(); + Result.MakeLValue(); + if (FromValue.hasLValuePath()) { + MutableArrayRef ToPath = Result.setLValueUninit( + Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(), + FromValue.isNullPointer()); + llvm::ArrayRef FromPath = + FromValue.getLValuePath(); + for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { + if (FromElemTy->isRecordType()) { + const Decl *FromDecl = + FromPath[LoopIdx].getAsBaseOrMember().getPointer(); + const Decl *ImpDecl = importChecked(Err, FromDecl); + if (Err) + return std::move(Err); + if (auto *RD = dyn_cast(FromDecl)) + FromElemTy = Importer.FromContext.getRecordType(RD); + else + FromElemTy = cast(FromDecl)->getType(); + ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType( + ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt())); + } else { + FromElemTy = + Importer.FromContext.getAsArrayType(FromElemTy)->getElementType(); + ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex( + FromPath[LoopIdx].getAsArrayIndex()); + } + } + } else + Result.setLValue(Base, Offset, APValue::NoLValuePath{}, + FromValue.isNullPointer()); + } + if (Err) + return std::move(Err); + return Result; +} + Expected ASTImporter::HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index f2502c327a118..0656efae5489f 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -835,6 +835,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ExternCContext: case Decomposition: case MSGuid: + case TemplateParamObject: case UsingDirective: case BuiltinTemplate: diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index d99a9c19c506e..9918377070c3a 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -1431,3 +1431,36 @@ void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { OS << ">"; } } + +TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C, + QualType T, + const APValue &V) { + DeclContext *DC = C.getTranslationUnitDecl(); + auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V); + C.addDestruction(&TPOD->Value); + return TPOD; +} + +TemplateParamObjectDecl * +TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue()); + C.addDestruction(&TPOD->Value); + return TPOD; +} + +void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS) const { + OS << "