diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 69c7369755c67..d82915b29ce54 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -387,6 +387,9 @@ Bug Fixes in This Version #if 1 ? 1 : 999999999999999999999 #endif +- ``#embed`` directive now diagnoses use of a non-character file (device file) + such as ``/dev/urandom`` as an error. This restriction may be relaxed in the + future. See (#GH126629). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 912b8bd46e194..f29edfa835d42 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -458,6 +458,8 @@ def warn_compat_pp_embed_directive : Warning< InGroup, DefaultIgnore; def err_pp_embed_dup_params : Error< "cannot specify parameter '%0' twice in the same '#embed' directive">; +def err_pp_embed_device_file : Error< + "device files are not yet supported by '#embed' directive">; def ext_pp_extra_tokens_at_eol : ExtWarn< "extra tokens at end of #%0 directive">, InGroup; diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index da5ba90974293..c973ba38bdf7e 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -82,6 +82,7 @@ class FileEntryRef { inline const llvm::sys::fs::UniqueID &getUniqueID() const; inline time_t getModificationTime() const; inline bool isNamedPipe() const; + inline bool isDeviceFile() const; inline void closeFile() const; /// Check if the underlying FileEntry is the same, intentially ignoring @@ -316,6 +317,7 @@ class FileEntry { llvm::sys::fs::UniqueID UniqueID; unsigned UID = 0; // A unique (small) ID for the file. bool IsNamedPipe = false; + bool IsDeviceFile = false; /// The open file, if it is owned by the \p FileEntry. mutable std::unique_ptr File; @@ -340,6 +342,7 @@ class FileEntry { /// Check whether the file is a named pipe (and thus can't be opened by /// the native FileManager methods). bool isNamedPipe() const { return IsNamedPipe; } + bool isDeviceFile() const { return IsDeviceFile; } void closeFile() const; }; @@ -357,6 +360,9 @@ time_t FileEntryRef::getModificationTime() const { } bool FileEntryRef::isNamedPipe() const { return getFileEntry().isNamedPipe(); } +bool FileEntryRef::isDeviceFile() const { + return getFileEntry().isDeviceFile(); +} void FileEntryRef::closeFile() const { getFileEntry().closeFile(); } diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index ec84aad72e6be..86fe352df0461 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -330,6 +330,8 @@ llvm::Expected FileManager::getFileRef(StringRef Filename, UFE->UID = NextFileUID++; UFE->UniqueID = Status.getUniqueID(); UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file; + UFE->IsDeviceFile = + Status.getType() == llvm::sys::fs::file_type::character_file; UFE->File = std::move(F); if (UFE->File) { diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index d97a6e8d64f9c..318b8fdad2e04 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -4010,6 +4010,12 @@ void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok, Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; } + + if (MaybeFileRef->isDeviceFile()) { + Diag(FilenameTok, diag::err_pp_embed_device_file) << Filename; + return; + } + std::optional MaybeFile = getSourceManager().getMemoryBufferForFileOrNone(*MaybeFileRef); if (!MaybeFile) { diff --git a/clang/test/Preprocessor/embed-reject-device-files-lin.c b/clang/test/Preprocessor/embed-reject-device-files-lin.c new file mode 100644 index 0000000000000..4c9744ad86d44 --- /dev/null +++ b/clang/test/Preprocessor/embed-reject-device-files-lin.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c23 %s -fsyntax-only -verify +// REQUIRES: system-linux + + +int urandom[] = { +#embed "/dev/urandom" //expected-error {{device files are not yet supported by '#embed' directive}} +}; +int random[] = { +#embed "/dev/random" //expected-error {{device files are not yet supported by '#embed' directive}} +}; +int zero[] = { +#embed "/dev/zero" //expected-error {{device files are not yet supported by '#embed' directive}} +}; +int null[] = { +#embed "/dev/null" //expected-error {{device files are not yet supported by '#embed' directive}} +}; diff --git a/clang/test/Preprocessor/embed-reject-device-files-win.c b/clang/test/Preprocessor/embed-reject-device-files-win.c new file mode 100644 index 0000000000000..640b59ab7535c --- /dev/null +++ b/clang/test/Preprocessor/embed-reject-device-files-win.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c23 %s -fsyntax-only -verify +// REQUIRES: system-windows + + +int null[] = { +#embed "NUL" limit(1) //expected-error {{device files are not yet supported by '#embed' directive}} +};