diff options
author | csilvers <csilvers@812d1f90-f944-d88a-411a-122bdc93e1ea> | 2012-03-06 23:19:16 +0000 |
---|---|---|
committer | csilvers <csilvers@812d1f90-f944-d88a-411a-122bdc93e1ea> | 2012-03-06 23:19:16 +0000 |
commit | c3064e48787afa2ee3ef7646dfd77ac2ccb245da (patch) | |
tree | cfaea1f52357fef42f46d0965f5629a8e65e02c3 | |
parent | 80118553e093513ca74a160f53d84b547d103543 (diff) |
Version of include-what-you-use that builds against llvm+clang 3.0; used to produce include-what-you-use-3.0-1.tar.gzclang_3.0
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | iwyu.cc | 5 | ||||
-rw-r--r-- | iwyu_ast_util.cc | 8 | ||||
-rw-r--r-- | iwyu_driver.cc | 6 | ||||
-rw-r--r-- | iwyu_globals.cc | 20 | ||||
-rw-r--r-- | iwyu_globals.h | 11 | ||||
-rw-r--r-- | iwyu_include_picker.cc | 63 | ||||
-rw-r--r-- | iwyu_include_picker.h | 19 | ||||
-rw-r--r-- | iwyu_lexer_utils.cc | 3 | ||||
-rw-r--r-- | iwyu_output.cc | 13 | ||||
-rw-r--r-- | iwyu_output.h | 22 | ||||
-rw-r--r-- | iwyu_path_util.cc | 181 | ||||
-rw-r--r-- | iwyu_path_util.h | 140 | ||||
-rw-r--r-- | iwyu_preprocessor.cc | 2 | ||||
-rw-r--r-- | iwyu_verrs.cc | 44 | ||||
-rw-r--r-- | iwyu_verrs.h | 45 | ||||
-rw-r--r-- | more_tests/iwyu_output_test.cc | 9 | ||||
-rw-r--r-- | tests/badinc.cc | 3 | ||||
-rw-r--r-- | tests/badinc.h | 4 | ||||
-rw-r--r-- | tests/fwd_decl_of_nested_class_defined_later.cc | 40 | ||||
-rw-r--r-- | tests/integer_template_arg.cc | 19 |
21 files changed, 236 insertions, 423 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1095a0e..96715e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,9 +31,7 @@ add_clang_executable(include-what-you-use iwyu_lexer_utils.cc iwyu_location_util.cc iwyu_output.cc - iwyu_path_util.cc iwyu_preprocessor.cc - iwyu_verrs.cc ) install(TARGETS include-what-you-use @@ -95,7 +95,6 @@ #include <stddef.h> // for size_t #include <stdio.h> // for snprintf #include <stdlib.h> // for atoi, exit -#include <string.h> #include <algorithm> // for swap, find, make_pair #include <deque> // for swap #include <iterator> // for find @@ -118,7 +117,6 @@ #include "iwyu_preprocessor.h" // IWYU pragma: keep #include "iwyu_stl_util.h" #include "iwyu_string_util.h" -#include "iwyu_verrs.h" #include "port.h" // for CHECK_ #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" @@ -1908,8 +1906,6 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { // These casts don't require any iwyu action. case clang::CK_LValueToRValue: - case clang::CK_AtomicToNonAtomic: - case clang::CK_NonAtomicToAtomic: break; // We shouldn't be seeing any of these kinds. @@ -1955,6 +1951,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { case clang::CK_ARCReclaimReturnedObject: case clang::CK_BlockPointerToObjCPointerCast: case clang::CK_CPointerToObjCPointerCast: + case clang::CK_GetObjCProperty: case clang::CK_ObjCObjectLValueCast: case clang::CK_VectorSplat: CHECK_(false && "TODO(csilvers): for objc and clang lang extensions"); diff --git a/iwyu_ast_util.cc b/iwyu_ast_util.cc index e05dfc9..135c5b8 100644 --- a/iwyu_ast_util.cc +++ b/iwyu_ast_util.cc @@ -17,10 +17,10 @@ #include "iwyu_globals.h" #include "iwyu_location_util.h" +#include "iwyu_output.h" #include "iwyu_path_util.h" #include "iwyu_stl_util.h" #include "iwyu_string_util.h" -#include "iwyu_verrs.h" #include "port.h" // for CHECK_ #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" @@ -224,9 +224,7 @@ bool IsNodeInsideCXXMethodBody(const ASTNode* ast_node) { } if (const CXXMethodDecl* method_decl = ast_node->GetParentAs<CXXMethodDecl>()) { - if (ast_node->ContentIs(method_decl->getBody())) { - return true; - } + return ast_node->ContentIs(method_decl->getBody()); } } return false; @@ -1244,7 +1242,7 @@ bool IsCastToReferenceType(const CastExpr* expr) { const ASTTemplateArgumentListInfo* GetExplicitTplArgs(const Expr* expr) { if (const DeclRefExpr* decl_ref = DynCastFrom(expr)) - return decl_ref->getOptionalExplicitTemplateArgs(); + return decl_ref->getExplicitTemplateArgsOpt(); if (const MemberExpr* member_expr = DynCastFrom(expr)) return member_expr->getOptionalExplicitTemplateArgs(); // Ugh, annoying casts needed because no const methods exist. diff --git a/iwyu_driver.cc b/iwyu_driver.cc index 7b73fbd..0dccfcd 100644 --- a/iwyu_driver.cc +++ b/iwyu_driver.cc @@ -25,7 +25,6 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/DiagnosticOptions.h" -#include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendDiagnostic.h" // IWYU pragma: keep #include "clang/Frontend/TextDiagnosticPrinter.h" @@ -57,7 +56,7 @@ using llvm::cast; using llvm::errs; using llvm::isa; using llvm::raw_svector_ostream; -using llvm::sys::getDefaultTargetTriple; +using llvm::sys::getHostTriple; using llvm::sys::Path; using std::set; @@ -158,8 +157,7 @@ CompilerInstance* CreateCompilerInstance(int argc, const char **argv) { IntrusiveRefCntPtr<DiagnosticIDs> diagnostic_id(new DiagnosticIDs()); DiagnosticsEngine diagnostics(diagnostic_id, diagnostic_client); - Driver driver(path.str(), getDefaultTargetTriple(), "a.out", false, - diagnostics); + Driver driver(path.str(), getHostTriple(), "a.out", false, diagnostics); driver.setTitle("include what you use"); // Expand out any response files passed on the command line diff --git a/iwyu_globals.cc b/iwyu_globals.cc index 922e202..642ca39 100644 --- a/iwyu_globals.cc +++ b/iwyu_globals.cc @@ -22,10 +22,9 @@ #include "iwyu_getopt.h" #include "iwyu_lexer_utils.h" #include "iwyu_location_util.h" -#include "iwyu_path_util.h" +#include "iwyu_output.h" #include "iwyu_stl_util.h" #include "iwyu_string_util.h" -#include "iwyu_verrs.h" #include "port.h" // for CHECK_, etc #include "llvm/Support/raw_ostream.h" #include "clang/AST/PrettyPrinter.h" @@ -42,6 +41,7 @@ namespace include_what_you_use { static CommandlineFlags* commandline_flags = NULL; static clang::SourceManager* source_manager = NULL; +static vector<HeaderSearchPath>* search_paths = NULL; static IncludePicker* include_picker = NULL; static const clang::LangOptions default_lang_options; static const clang::PrintingPolicy default_print_policy(default_lang_options); @@ -117,7 +117,6 @@ int ParseIwyuCommandlineFlags(int argc, char** argv) { CHECK_(commandline_flags == NULL && "Only parse commandline flags once"); commandline_flags = new CommandlineFlags; const int retval = commandline_flags->ParseArgv(argc, argv); - SetVerboseLevel(commandline_flags->verbose); if (!commandline_flags->cwd.empty()) { printf("-p/--cwd not yet implemented\n"); @@ -185,14 +184,13 @@ void InitGlobals(clang::SourceManager* sm, clang::HeaderSearch* header_search) { CHECK_(sm && "InitGlobals() needs a non-NULL SourceManager"); source_manager = sm; data_getter = new SourceManagerCharacterDataGetter(*source_manager); - vector<HeaderSearchPath> search_paths = - ComputeHeaderSearchPaths(header_search); - SetHeaderSearchPaths(search_paths); + search_paths = new vector<HeaderSearchPath>( + ComputeHeaderSearchPaths(header_search)); include_picker = new IncludePicker; function_calls_full_use_cache = new FullUseCache; class_members_full_use_cache = new FullUseCache; - for (Each<HeaderSearchPath> it(&search_paths); !it.AtEnd(); ++it) { + for (Each<HeaderSearchPath> it(search_paths); !it.AtEnd(); ++it) { const char* path_type_name = (it->path_type == HeaderSearchPath::kSystemPath ? "system" : "user"); VERRS(6) << "Search path: " << it->path << " (" << path_type_name << ")\n"; @@ -214,6 +212,11 @@ clang::SourceManager* GlobalSourceManager() { return source_manager; } +const vector<HeaderSearchPath>& GlobalHeaderSearchPaths() { + assert(search_paths && "Must call InitGlobals() before calling this"); + return *search_paths; +} + const IncludePicker& GlobalIncludePicker() { CHECK_(include_picker && "Must call InitGlobals() before calling this"); return *include_picker; @@ -272,7 +275,8 @@ void InitGlobalsAndFlagsForTesting() { search_path_map["."] = HeaderSearchPath::kUserPath; search_path_map["/usr/src/linux-headers-2.6.24-gg23/include"] = HeaderSearchPath::kSystemPath; - SetHeaderSearchPaths(NormalizeHeaderSearchPaths(search_path_map)); + search_paths = new vector<HeaderSearchPath>( + NormalizeHeaderSearchPaths(search_path_map)); } } // namespace include_what_you_use diff --git a/iwyu_globals.h b/iwyu_globals.h index 3e68fe1..ac86b3b 100644 --- a/iwyu_globals.h +++ b/iwyu_globals.h @@ -76,12 +76,23 @@ struct CommandlineFlags { int verbose; // -v: how much information to emit as we parse }; +// One entry in the search-path list of where to find #include files. +struct HeaderSearchPath { + enum Type { kUnusedPath = 0, kSystemPath, kUserPath }; + HeaderSearchPath(const string& p, Type pt) : path(p), path_type(pt) { } + string path; // the path-entry as specified on the commandline (via -I) + Type path_type; +}; + const CommandlineFlags& GlobalFlags(); // Used by tests as an easy way to simulate calling with different --flags. CommandlineFlags* MutableGlobalFlagsForTesting(); clang::SourceManager* GlobalSourceManager(); +// The directories to look for #includes in, including from -I, -isystem, etc. +const vector<HeaderSearchPath>& GlobalHeaderSearchPaths(); + const IncludePicker& GlobalIncludePicker(); IncludePicker* MutableGlobalIncludePicker(); // only use at great need! diff --git a/iwyu_include_picker.cc b/iwyu_include_picker.cc index 12bb057..cea409e 100644 --- a/iwyu_include_picker.cc +++ b/iwyu_include_picker.cc @@ -15,19 +15,18 @@ #include <iterator> // for find // not hash_map: it's not as portable and needs hash<string>. #include <map> // for map, map<>::mapped_type, etc -#include <ostream> #include <string> // for string, basic_string, etc #include <utility> // for pair, make_pair #include <vector> // for vector, vector<>::iterator +#include "iwyu_globals.h" +#include "iwyu_output.h" #include "iwyu_path_util.h" #include "iwyu_stl_util.h" #include "iwyu_string_util.h" -#include "iwyu_verrs.h" #include "port.h" // for CHECK_ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" -#include "llvm/Support/raw_ostream.h" using std::find; using std::map; @@ -600,7 +599,6 @@ const IncludePicker::IncludeMapEntry cpp_include_map[] = { // I don't think we want to be having people move to 'backward/' // yet. (These hold deprecated STL classes that we still use // actively.) These are the ones that turned up in an analysis of - { "<backward/auto_ptr.h>", kPrivate, "<memory>", kPublic }, { "<backward/binders.h>", kPrivate, "<functional>", kPublic }, { "<backward/hash_fun.h>", kPrivate, "<hash_map>", kPublic }, { "<backward/hash_fun.h>", kPrivate, "<hash_set>", kPublic }, @@ -609,7 +607,6 @@ const IncludePicker::IncludeMapEntry cpp_include_map[] = { { "<backward/strstream>", kPrivate, "<strstream>", kPublic }, // We have backward as part of the -I search path now, so have the // non-backwards-prefix version as well. - { "<auto_ptr.h>", kPrivate, "<memory>", kPublic }, { "<binders.h>", kPrivate, "<functional>", kPublic }, { "<hash_fun.h>", kPrivate, "<hash_map>", kPublic }, { "<hash_fun.h>", kPrivate, "<hash_set>", kPublic }, @@ -819,8 +816,64 @@ void MakeMapTransitive(IncludePicker::IncludeMap* filename_map) { MakeNodeTransitive(filename_map, &seen_nodes, &node_stack, it->first); } + } // namespace +// Converts a file-path, such as /usr/include/stdio.h, to a +// quoted include, such as <stdio.h>. +string ConvertToQuotedInclude(const string& filepath) { + // First, get rid of leading ./'s and the like. + string path = NormalizeFilePath(filepath); + + // Case 1: Uses an explicit entry on the search path (-I) list. + const vector<HeaderSearchPath>& search_paths = GlobalHeaderSearchPaths(); + // GlobalHeaderSearchPaths is sorted to be longest-first, so this + // loop will prefer the longest prefix: /usr/include/c++/4.4/foo + // will be mapped to <foo>, not <c++/4.4/foo>. + for (Each<HeaderSearchPath> it(&search_paths); !it.AtEnd(); ++it) { + if (StripLeft(&path, it->path)) { + StripLeft(&path, "/"); + if (it->path_type == HeaderSearchPath::kSystemPath) + return "<" + path + ">"; + else + return "\"" + path + "\""; + } + } + + + // Case 2: Uses the implicit "-I." entry on the search path. Always local. + return "\"" + path + "\""; +} + +bool IsQuotedInclude(const string& s) { + if (s.size() < 2) + return false; + return ((StartsWith(s, "<") && EndsWith(s, ">")) || + (StartsWith(s, "\"") && EndsWith(s, "\""))); +} + +// Returns whether this is a system (as opposed to user) include file, +// based on where it lives. +bool IsSystemIncludeFile(const string& filepath) { + return ConvertToQuotedInclude(filepath)[0] == '<'; +} + +// Returns true if the given file is third-party. Google-authored +// code living in third_party/ is not considered third-party. +bool IsThirdPartyFile(string quoted_path) { + if (!StripLeft("ed_path, "\"third_party/")) + return false; + + // These are Google-authored libraries living in third_party/ + // because of old licensing constraints. + if (StartsWith(quoted_path, "car/") || + StartsWith(quoted_path, "gtest/") || + StartsWith(quoted_path, "gmock/")) + return false; + + return true; +} + #define IWYU_ARRAYSIZE(ar) (sizeof(ar) / sizeof(*(ar))) IncludePicker::IncludePicker() diff --git a/iwyu_include_picker.h b/iwyu_include_picker.h index 6834693..652b796 100644 --- a/iwyu_include_picker.h +++ b/iwyu_include_picker.h @@ -59,6 +59,25 @@ using std::string; using std::vector; +// Below, we talk 'quoted' includes. A quoted include is something +// that would be written on an #include line, complete with the <> or +// "". In the line '#include <time.h>', "<time.h>" is the quoted +// include. + +// Converts a file-path, such as /usr/include/stdio.h, to a +// quoted include, such as <stdio.h>. +string ConvertToQuotedInclude(const string& filepath); + +bool IsQuotedInclude(const string& s); + +// Returns whether this is a system (as opposed to user) include +// file, based on where it lives. +bool IsSystemIncludeFile(const string& filepath); + +// Returns true if the given file is third-party. Google-authored +// code living in third_party/ is not considered third-party. +bool IsThirdPartyFile(string quoted_path); + class IncludePicker { public: enum Visibility { kUnusedVisibility, kPublic, kPrivate }; diff --git a/iwyu_lexer_utils.cc b/iwyu_lexer_utils.cc index 81f57e4..ca17340 100644 --- a/iwyu_lexer_utils.cc +++ b/iwyu_lexer_utils.cc @@ -10,11 +10,10 @@ #include "iwyu_lexer_utils.h" -#include <string.h> #include <string> #include <vector> -#include "iwyu_verrs.h" +#include "iwyu_output.h" #include "port.h" #include "llvm/Support/raw_ostream.h" #include "clang/Basic/LangOptions.h" diff --git a/iwyu_output.cc b/iwyu_output.cc index 1a84e56..a83f878 100644 --- a/iwyu_output.cc +++ b/iwyu_output.cc @@ -25,7 +25,6 @@ #include "iwyu_preprocessor.h" // IWYU pragma: keep #include "iwyu_stl_util.h" #include "iwyu_string_util.h" -#include "iwyu_verrs.h" // TODO(wan): remove this once the IWYU bug is fixed. // IWYU pragma: no_include "foo/bar/baz.h" #include "llvm/Support/Casting.h" @@ -63,6 +62,18 @@ using std::pair; using std::sort; using std::vector; +bool ShouldPrintSymbolFromFile(const FileEntry* file) { + if (GlobalFlags().verbose < 5) { + return false; + } else if (GlobalFlags().verbose < 10) { + return ShouldReportIWYUViolationsFor(file); + } else if (GlobalFlags().verbose < 11) { + return !IsSystemIncludeFile(GetFilePath(file)); + } else { + return true; + } +} + namespace internal { namespace { diff --git a/iwyu_output.h b/iwyu_output.h index 4954750..c05a782 100644 --- a/iwyu_output.h +++ b/iwyu_output.h @@ -11,7 +11,7 @@ // iwyu plug-in. This includes functions to sanitize include-files // (though most of the underlying logic is in iwyu_sanitize_filepath), // to sanitize symbol names, to emit desired include-lines properly, -// etc. +// etc. It also controls logging and verbosity levels. #ifndef DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_OUTPUT_H_ #define DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_OUTPUT_H_ @@ -21,8 +21,10 @@ #include <string> // for string, operator< #include <vector> // for vector +#include "iwyu_globals.h" #include "iwyu_stl_util.h" #include "port.h" // for CHECK_ +#include "llvm/Support/raw_ostream.h" #include "clang/AST/Decl.h" #include "clang/Basic/SourceLocation.h" @@ -41,6 +43,24 @@ using std::vector; class IwyuPreprocessorInfo; +// Returns true if we should print a message at the given verbosity level. +inline bool ShouldPrint(int verbose_level) { + return verbose_level <= GlobalFlags().verbose; +} + +// Returns true if we should print information about a symbol in the +// given file, at the current verbosity level. For instance, at most +// normal verbosities, we don't print information about symbols in +// system header files. +bool ShouldPrintSymbolFromFile(const clang::FileEntry* file); + +// VERRS(n) << blah; +// prints blah to errs() if the verbose level is >= n. +#define VERRS(verbose_level) \ + if (!::include_what_you_use::ShouldPrint( \ + verbose_level)) ; else ::llvm::errs() + + // This data structure holds information about a single use. Not all // fields will be filled for all uses. class OneUse { diff --git a/iwyu_path_util.cc b/iwyu_path_util.cc deleted file mode 100644 index cd9e3f2..0000000 --- a/iwyu_path_util.cc +++ /dev/null @@ -1,181 +0,0 @@ -//===--- iwyu_path_util.cc - path utilities for iwyu ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "iwyu_path_util.h" - -#include <stddef.h> - -#include "iwyu_stl_util.h" - -namespace include_what_you_use { - -namespace { -vector<HeaderSearchPath>* header_search_paths; -} // namespace - -void SetHeaderSearchPaths(const vector<HeaderSearchPath>& search_paths) { - if (header_search_paths != NULL) { - delete header_search_paths; - } - header_search_paths = new vector<HeaderSearchPath>(search_paths); -} - -const vector<HeaderSearchPath>& HeaderSearchPaths() { - if (header_search_paths == NULL) { - header_search_paths = new vector<HeaderSearchPath>(); - } - return *header_search_paths; -} - -namespace { - -} // namespace - -bool IsHeaderFile(string path) { - if (EndsWith(path, "\"") || EndsWith(path, ">")) - path = path.substr(0, path.length() - 1); - - // Some headers don't have an extension (e.g. <string>), or have an - // unusual one (the compiler doesn't care), so it's safer to - // enumerate non-header extensions instead. - if (EndsWith(path, ".cc") || EndsWith(path, ".c") || - EndsWith(path, ".cxx") || EndsWith(path, ".cpp")) - return false; - return true; -} - -string GetCWD() { - char cwd[PATH_MAX]; - if (getcwd(cwd, sizeof(cwd))) - return cwd; - return ""; -} - -string Basename(const string& path) { - string::size_type last_slash = path.rfind('/'); - if (last_slash != string::npos) { - return path.substr(last_slash + 1); - } - return path; -} - -string CanonicalizeFilePath(const string& path) { - string result = path; - -#ifdef _MSC_VER - // canonicalise directory separators (forward slashes considered canonical) - for (size_t i = 0; i < result.size(); ++i) { - if (result[i] == '\\') - result[i] = '/'; - } -#endif - - // We may also want to collapse ../ here. - - return result; -} - -string GetCanonicalName(string file_path) { - // Get rid of any <> and "" in case file_path is really an #include line. - StripLeft(&file_path, "\"") || StripLeft(&file_path, "<"); - StripRight(&file_path, "\"") || StripRight(&file_path, ">"); - - file_path = CanonicalizeFilePath(file_path); - - StripRight(&file_path, ".h") - || StripRight(&file_path, ".hpp") - || StripRight(&file_path, ".hxx") - || StripRight(&file_path, ".hh") - || StripRight(&file_path, ".inl") - || StripRight(&file_path, ".cxx") - || StripRight(&file_path, ".cpp") - || StripRight(&file_path, ".cc") - || StripRight(&file_path, ".c"); - StripRight(&file_path, "_unittest") - || StripRight(&file_path, "_regtest") - || StripRight(&file_path, "_test") - || StripLeft(&file_path, "test_headercompile_"); - StripRight(&file_path, "-inl"); - // .h files in /public/ match .cc files in /internal/ - const string::size_type internal_pos = file_path.find("/internal/"); - if (internal_pos != string::npos) - file_path = (file_path.substr(0, internal_pos) + "/public/" + - file_path.substr(internal_pos + strlen("/internal/"))); - - // .h files in /include/ match .cc files in /src/ - const string::size_type include_pos = file_path.find("/include/"); - if (include_pos != string::npos) - file_path = (file_path.substr(0, include_pos) + "/src/" + - file_path.substr(include_pos + strlen("/include/"))); - return file_path; -} - -string NormalizeFilePath(const string& path) { - string result = CanonicalizeFilePath(path); - while (StripLeft(&result, "./")) { - } - return result; -} - -// Converts a file-path, such as /usr/include/stdio.h, to a -// quoted include, such as <stdio.h>. -string ConvertToQuotedInclude(const string& filepath) { - // First, get rid of leading ./'s and the like. - string path = NormalizeFilePath(filepath); - - // Case 1: Uses an explicit entry on the search path (-I) list. - const vector<HeaderSearchPath>& search_paths = HeaderSearchPaths(); - // HeaderSearchPaths is sorted to be longest-first, so this - // loop will prefer the longest prefix: /usr/include/c++/4.4/foo - // will be mapped to <foo>, not <c++/4.4/foo>. - for (Each<HeaderSearchPath> it(&search_paths); !it.AtEnd(); ++it) { - if (StripLeft(&path, it->path)) { - StripLeft(&path, "/"); - if (it->path_type == HeaderSearchPath::kSystemPath) - return "<" + path + ">"; - else - return "\"" + path + "\""; - } - } - - - // Case 2: Uses the implicit "-I." entry on the search path. Always local. - return "\"" + path + "\""; -} - -bool IsQuotedInclude(const string& s) { - if (s.size() < 2) - return false; - return ((StartsWith(s, "<") && EndsWith(s, ">")) || - (StartsWith(s, "\"") && EndsWith(s, "\""))); -} - -// Returns whether this is a system (as opposed to user) include file, -// based on where it lives. -bool IsSystemIncludeFile(const string& filepath) { - return ConvertToQuotedInclude(filepath)[0] == '<'; -} - -// Returns true if the given file is third-party. Google-authored -// code living in third_party/ is not considered third-party. -bool IsThirdPartyFile(string quoted_path) { - if (!StripLeft("ed_path, "\"third_party/")) - return false; - - // These are Google-authored libraries living in third_party/ - // because of old licensing constraints. - if (StartsWith(quoted_path, "car/") || - StartsWith(quoted_path, "gtest/") || - StartsWith(quoted_path, "gmock/")) - return false; - - return true; -} - -} // namespace include_what_you_use diff --git a/iwyu_path_util.h b/iwyu_path_util.h index c4ec715..b956d6c 100644 --- a/iwyu_path_util.h +++ b/iwyu_path_util.h @@ -20,72 +20,102 @@ #include <unistd.h> // for getcwd #endif #include <string> // for string, allocator, etc -#include <vector> #include "iwyu_string_util.h" namespace include_what_you_use { using std::string; -using std::vector; -// One entry in the search-path list of where to find #include files. -struct HeaderSearchPath { - enum Type { kUnusedPath = 0, kSystemPath, kUserPath }; - HeaderSearchPath(const string& p, Type pt) : path(p), path_type(pt) { } - string path; // the path-entry as specified on the commandline (via -I) - Type path_type; -}; - -// The directories to look for #includes in, including from -I, -isystem, etc. -void SetHeaderSearchPaths(const vector<HeaderSearchPath>& search_paths); -const vector<HeaderSearchPath>& HeaderSearchPaths(); - // Returns true if 'path' is a path of a (possibly enclosed in double // quotes or <>) C++ header file. -bool IsHeaderFile(string path); - -// Return the current working directory of this process. -string GetCWD(); - -// If the path has a slash, return the part after the last slash, -// else return the input path. -string Basename(const string& path); - -// On Microsoft platforms, convert \ to /. -string CanonicalizeFilePath(const string& path); - -// Removes enclosing <> or "", then strips uninteresting suffixes from -// the file name. Replaces "/internal/" with "/public/" and -// "/include/" with "/src". "Canonicalize" the path on Microsoft -// platforms. -string GetCanonicalName(string file_path); - - -// "Canonicals" the name on Microsoft platforms, then recursively -// removes all "./" prefixes. -string NormalizeFilePath(const string& path); - -// Below, we talk 'quoted' includes. A quoted include is something -// that would be written on an #include line, complete with the <> or -// "". In the line '#include <time.h>', "<time.h>" is the quoted -// include. - -// Converts a file-path, such as /usr/include/stdio.h, to a -// quoted include, such as <stdio.h>. -string ConvertToQuotedInclude(const string& filepath); - -// Returns true if the string is a quoted include. -bool IsQuotedInclude(const string& s); - -// Returns whether this is a system (as opposed to user) include -// file, based on where it lives. -bool IsSystemIncludeFile(const string& filepath); +inline bool IsHeaderFile(string path) { + if (EndsWith(path, "\"") || EndsWith(path, ">")) + path = path.substr(0, path.length() - 1); + + // Some headers don't have an extension (e.g. <string>), or have an + // unusual one (the compiler doesn't care), so it's safer to + // enumerate non-header extensions instead. + if (EndsWith(path, ".cc") || EndsWith(path, ".c") || + EndsWith(path, ".cxx") || EndsWith(path, ".cpp")) + return false; + return true; +} + +inline string GetCWD() { + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd))) + return cwd; + return ""; +} + +inline string Basename(const string& path) { + string::size_type last_slash = path.rfind('/'); + if (last_slash != string::npos) { + return path.substr(last_slash + 1); + } + return path; +} + +inline string CanonicalizeFilePath(const string& path) { + string result = path; + +#ifdef _MSC_VER + // canonicalise directory separators (forward slashes considered canonical) + for (size_t i = 0; i < result.size(); ++i) { + if (result[i] == '\\') + result[i] = '/'; + } +#endif -// Returns true if the given file is third-party. Google-authored -// code living in third_party/ is not considered third-party. -bool IsThirdPartyFile(string quoted_path); + // We may also want to collapse ../ here. + + return result; +} + +// Strips uninteresting suffixes from the file name. +inline string GetCanonicalName(string file_path) { + // Get rid of any <> and "" in case file_path is really an #include line. + StripLeft(&file_path, "\"") || StripLeft(&file_path, "<"); + StripRight(&file_path, "\"") || StripRight(&file_path, ">"); + + file_path = CanonicalizeFilePath(file_path); + + StripRight(&file_path, ".h") + || StripRight(&file_path, ".hpp") + || StripRight(&file_path, ".hxx") + || StripRight(&file_path, ".hh") + || StripRight(&file_path, ".inl") + || StripRight(&file_path, ".cxx") + || StripRight(&file_path, ".cpp") + || StripRight(&file_path, ".cc") + || StripRight(&file_path, ".c"); + StripRight(&file_path, "_unittest") + || StripRight(&file_path, "_regtest") + || StripRight(&file_path, "_test") + || StripLeft(&file_path, "test_headercompile_"); + StripRight(&file_path, "-inl"); + // .h files in /public/ match .cc files in /internal/ + const string::size_type internal_pos = file_path.find("/internal/"); + if (internal_pos != string::npos) + file_path = (file_path.substr(0, internal_pos) + "/public/" + + file_path.substr(internal_pos + strlen("/internal/"))); + + // .h files in /include/ match .cc files in /src/ + const string::size_type include_pos = file_path.find("/include/"); + if (include_pos != string::npos) + file_path = (file_path.substr(0, include_pos) + "/src/" + + file_path.substr(include_pos + strlen("/include/"))); + return file_path; +} + +inline string NormalizeFilePath(const string& path) { + string result = CanonicalizeFilePath(path); + while (StripLeft(&result, "./")) { + } + return result; +} } // namespace include_what_you_use diff --git a/iwyu_preprocessor.cc b/iwyu_preprocessor.cc index 9745362..a0ed157 100644 --- a/iwyu_preprocessor.cc +++ b/iwyu_preprocessor.cc @@ -11,7 +11,6 @@ #include "iwyu_preprocessor.h" #include <stddef.h> // for size_t -#include <string.h> #include <string> // for string, basic_string, etc #include <utility> // for pair, make_pair @@ -24,7 +23,6 @@ #include "iwyu_path_util.h" #include "iwyu_stl_util.h" #include "iwyu_string_util.h" -#include "iwyu_verrs.h" #include "port.h" // for CHECK_ // TODO(wan): remove this once the IWYU bug is fixed. // IWYU pragma: no_include "foo/bar/baz.h" diff --git a/iwyu_verrs.cc b/iwyu_verrs.cc deleted file mode 100644 index 8995f3a..0000000 --- a/iwyu_verrs.cc +++ /dev/null @@ -1,44 +0,0 @@ -//===--- iwyu_verrs.h - debug output for include-what-you-use ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "iwyu_verrs.h" - -#include "iwyu_globals.h" -#include "iwyu_location_util.h" -#include "iwyu_path_util.h" - -namespace include_what_you_use { - -using clang::FileEntry; - -namespace { -int verbose_level = 1; -} // namespace - -void SetVerboseLevel(int level) { - verbose_level = level; -} - -int GetVerboseLevel() { - return verbose_level; -} - -bool ShouldPrintSymbolFromFile(const FileEntry* file) { - if (GetVerboseLevel() < 5) { - return false; - } else if (GetVerboseLevel() < 10) { - return ShouldReportIWYUViolationsFor(file); - } else if (GetVerboseLevel() < 11) { - return !IsSystemIncludeFile(GetFilePath(file)); - } else { - return true; - } -} - -} // namespace include_what_you_use diff --git a/iwyu_verrs.h b/iwyu_verrs.h deleted file mode 100644 index b816d40..0000000 --- a/iwyu_verrs.h +++ /dev/null @@ -1,45 +0,0 @@ -//===--- iwyu_verrs.h - debug output for include-what-you-use ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This module controls logging and verbosity levels for include-what-you-use. - -#ifndef DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_VERRS_H_ -#define DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_VERRS_H_ - -#include "llvm/Support/raw_ostream.h" - -namespace clang { -class FileEntry; -} - -namespace include_what_you_use { - -void SetVerboseLevel(int level); -int GetVerboseLevel(); - -// Returns true if we should print a message at the given verbosity level. -inline bool ShouldPrint(int verbose_level) { - return verbose_level <= GetVerboseLevel(); -} - -// Returns true if we should print information about a symbol in the -// given file, at the current verbosity level. For instance, at most -// normal verbosities, we don't print information about symbols in -// system header files. -bool ShouldPrintSymbolFromFile(const clang::FileEntry* file); - -// VERRS(n) << blah; -// prints blah to errs() if the verbose level is >= n. -#define VERRS(verbose_level) \ - if (!::include_what_you_use::ShouldPrint( \ - verbose_level)) ; else ::llvm::errs() - -} // namespace include_what_you_use - -#endif // DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_VERRS_H_ diff --git a/more_tests/iwyu_output_test.cc b/more_tests/iwyu_output_test.cc index 434e9d0..a41a822 100644 --- a/more_tests/iwyu_output_test.cc +++ b/more_tests/iwyu_output_test.cc @@ -11,15 +11,14 @@ #include "iwyu_output.h" -#include <stddef.h> #include <set> #include "iwyu_ast_util.h" #include "iwyu_globals.h" -#include "iwyu_verrs.h" #include "testing/base/public/gunit.h" #undef ATTRIBUTE_UNUSED +#include "clang/AST/Decl.h" #include "clang/Basic/SourceLocation.h" using clang::NamedDecl; @@ -233,7 +232,7 @@ TEST(CalculateDesiredIncludesAndForwardDeclaresTest, Works) { // between tests to prevent leaking side effects. class VerboseTest : public ::testing::Test { protected: - VerboseTest() : old_verbose_level_(GetVerboseLevel()) { + VerboseTest() : old_verbose_level_(GlobalFlags().verbose) { // 2 is the default verbose level for tests that don't care much // about the level. SetVerboseLevel(2); @@ -243,6 +242,10 @@ class VerboseTest : public ::testing::Test { SetVerboseLevel(old_verbose_level_); } + void SetVerboseLevel(int level) { + MutableGlobalFlagsForTesting()->verbose = level; + } + private: const int old_verbose_level_; }; diff --git a/tests/badinc.cc b/tests/badinc.cc index 6a7e268..ed28309 100644 --- a/tests/badinc.cc +++ b/tests/badinc.cc @@ -131,6 +131,8 @@ int i1_macro_symbol_with_value_and_value2_var2; #if __LINE__ || __STDC__ || defined(__cplusplus) #endif +extern "C" std::string Flag3Value() { return 0; } + // Using declarations and statements. // TODO(csilvers): I don't see a consistent way to say whether // "i1_ns2" is an iwyu violation or not, since namespaces can be @@ -264,7 +266,6 @@ class MultipleInheritanceSubclass : public I2_ThisClassIsOnlySubclassed, // IWYU: I2_Class is...*badinc-i2.h virtual I2_Class { public: - // IWYU: I2_Class is...*badinc-i2.h // IWYU: I2_Struct is...*badinc-i2.h // IWYU: I2_MACRO is...*badinc-i2.h MultipleInheritanceSubclass() : I2_Class(I2_Struct().a + I2_MACRO) { } diff --git a/tests/badinc.h b/tests/badinc.h index 22700ff..5a13bee 100644 --- a/tests/badinc.h +++ b/tests/badinc.h @@ -130,6 +130,8 @@ class H_Class { case I21: return 21; // IWYU: I22 is...*badinc-i2.h case I22: return 22; + // IWYU: I23 is...*badinc-i2.h + case I23: return 23; default: return errno; } } @@ -404,7 +406,7 @@ The full include-list for tests/badinc.h: #include <vector> // for vector #include "tests/badinc-d3.h" // for D3_Enum, D3_Enum::D31 #include "tests/badinc-i2-inl.h" // for I2_Class::I2_Class, I2_Class::InlFileFn, I2_Class::InlFileStaticFn, I2_Class::InlFileTemplateFn, I2_Class::~I2_Class, I2_TemplateClass::I2_TemplateClass<FOO>, I2_TemplateClass::InlFileTemplateClassFn, I2_TemplateClass::~I2_TemplateClass<FOO> -#include "tests/badinc-i2.h" // for I2_Class, I2_Enum, I2_Enum::I21, I2_Enum::I22, I2_EnumForTypedefs, I2_MACRO, I2_Struct, I2_TemplateClass, I2_Typedef, I2_TypedefOnly_Class (ptr only), TemplateForHClassTplFn (ptr only) +#include "tests/badinc-i2.h" // for I2_Class, I2_Enum, I2_Enum::I21, I2_Enum::I22, I2_Enum::I23, I2_EnumForTypedefs, I2_MACRO, I2_Struct, I2_TemplateClass, I2_Typedef, I2_TypedefOnly_Class (ptr only), TemplateForHClassTplFn (ptr only) class Cc_Class; // lines XX-XX // TODO(csilvers): this should change to struct Cc_Struct. class Cc_Struct; // lines XX-XX diff --git a/tests/fwd_decl_of_nested_class_defined_later.cc b/tests/fwd_decl_of_nested_class_defined_later.cc deleted file mode 100644 index 69159fc..0000000 --- a/tests/fwd_decl_of_nested_class_defined_later.cc +++ /dev/null @@ -1,40 +0,0 @@ -//===--- fwd_decl_of_nested_class_defined_later.cc - test input file for iwyu ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// This tests a particular situation which until recently IWYU did not -// handle correctly. In certain cases, it would have unnecessarily recommended -// a forward declaration *outside* of a class definition which really -// belonged inside the class definition. - -#include <utility> - -class Foo { - private: - int Bar() { - // The bug was that in the AST tree that IWYU generates, a - // CXXMethodDecl node representing the pair destructor declaration - // intervened in the chain from the node corresponding to the use - // of Baz up to the CXXMethodDecl node for Bar. This caused - // IsNodeInsideCXXMethodBody to return false for the node - // corresponding to the use of Baz. - // The fix was to not stop at the destructor declaration when - // walking up the tree, since the context was not the body of the - // destructor. - return std::make_pair(Baz(), 0).second; - } - - struct Baz { - int value_; - }; -}; - -/**** IWYU_SUMMARY - -(tests/fwd_decl_of_nested_class_defined_later.cc has correct #includes/fwd-decls) - -***** IWYU_SUMMARY */ diff --git a/tests/integer_template_arg.cc b/tests/integer_template_arg.cc deleted file mode 100644 index c11db7f..0000000 --- a/tests/integer_template_arg.cc +++ /dev/null @@ -1,19 +0,0 @@ -//===--- integer_template_arg.cc - test input file for iwyu ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This is a test to make sure a Clang crashing bug doesn't regress. - -template <int Arg> class Base {}; -class Derived : public Base<1> {}; - -/**** IWYU_SUMMARY - -(tests/integer_template_arg.cc has correct #includes/fwd-decls) - -***** IWYU_SUMMARY */ |