1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang-tidy/ClangTidyCheck.h"
10 
11 #include "llvm/ADT/StringRef.h"
12 
13 #include <fstream>
14 #include <set>
15 #include <string>
16 
17 namespace libcpp {
18 class header_exportable_declarations : public clang::tidy::ClangTidyCheck {
19 public:
20   explicit header_exportable_declarations(llvm::StringRef, clang::tidy::ClangTidyContext*);
21   ~header_exportable_declarations();
22   void registerMatchers(clang::ast_matchers::MatchFinder*) override;
23   void check(const clang::ast_matchers::MatchFinder::MatchResult&) override;
24 
25   enum class FileType {
26     // std module specific
27     Header,
28     CompatModulePartition,
29     Module,
30     // std.compat module specific
31     CHeader,
32     ModulePartition,
33     CompatModule,
34     // invalid value
35     Unknown
36   };
37 
38 private:
39   llvm::StringRef filename_;
40   FileType file_type_;
41   llvm::StringRef extra_header_;
42   std::set<std::string> decls_;
43   std::set<std::string> global_decls_;
44 
45   // The named declarations in .h C headers are "tricky". On POSIX
46   // systems these headers contain POSIX specific functions that do not
47   // use a reserved name. For example, fmemopen is provided by stdio.h.
48   // We filter the names that should be provided by the headers as follows:
49   // - record all named declarations the global namespace
50   // - wait until the header is completely processed
51   // - every named declaration in the global namespace that has a matching
52   //   "export" in the std namespace is exported.
53   //
54   // The only place where we can do the above while ensuring that all
55   // the declarations in the header have been seen is in the clang tidy
56   // plugin's destructor.
57   //
58   // It is possible to skip some declarations in the std namespace,
59   // these are added to decls_ before processing. To differentiate
60   // between a skipped declaration and a real declaration the skipped
61   // declarations are recorded in an extra variable.
62   std::set<std::string> skip_decls_;
63 };
64 } // namespace libcpp
65