diff --git a/clang-tools-extra/docs/ModularizeUsage.rst b/clang-tools-extra/docs/ModularizeUsage.rst index dc335431ba74..6ac5d53d0bd9 100644 --- a/clang-tools-extra/docs/ModularizeUsage.rst +++ b/clang-tools-extra/docs/ModularizeUsage.rst @@ -49,3 +49,10 @@ Modularize Command Line Options Put modules generated by the -module-map-path option in an enclosing module with the given name. See the description in :ref:`module-map-generation`. + +.. option:: -block-check-header-list-only + + Limit the #include-inside-extern-or-namespace-block + check to only those headers explicitly listed in the header list. + This is a work-around for avoiding error messages for private includes that + purposefully get included inside blocks. diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 49b2de045b1a..3504b75560b0 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -209,6 +209,15 @@ cl::opt RootModule("root-module", cl::init(""), cl::desc("Specify the name of the root module.")); +// Option for limiting the #include-inside-extern-or-namespace-block +// check to only those headers explicitly listed in the header list. +// This is a work-around for private includes that purposefully get +// included inside blocks. +static cl::opt +BlockCheckHeaderListOnly("block-check-header-list-only", cl::init(false), +cl::desc("Only warn if #include directives are inside extern or namespace" + " blocks if the included header is in the header list.")); + // Save the program name for error messages. const char *Argv0; // Save the command line for comments. @@ -722,7 +731,8 @@ int main(int Argc, const char **Argv) { new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments)); // Create preprocessor tracker, to watch for macro and conditional problems. - std::unique_ptr PPTracker(PreprocessorTracker::create()); + std::unique_ptr PPTracker( + PreprocessorTracker::create(Headers, BlockCheckHeaderListOnly)); // Parse all of the headers, detecting duplicates. EntityMap Entities; diff --git a/clang-tools-extra/modularize/PreprocessorTracker.cpp b/clang-tools-extra/modularize/PreprocessorTracker.cpp index 685e242032c7..2a41921cb463 100644 --- a/clang-tools-extra/modularize/PreprocessorTracker.cpp +++ b/clang-tools-extra/modularize/PreprocessorTracker.cpp @@ -866,9 +866,19 @@ ConditionalExpansionMapIter; // course of running modularize. class PreprocessorTrackerImpl : public PreprocessorTracker { public: - PreprocessorTrackerImpl() - : CurrentInclusionPathHandle(InclusionPathHandleInvalid), - InNestedHeader(false) {} + PreprocessorTrackerImpl(llvm::SmallVector &Headers, + bool DoBlockCheckHeaderListOnly) + : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly), + CurrentInclusionPathHandle(InclusionPathHandleInvalid), + InNestedHeader(false) { + // Use canonical header path representation. + for (llvm::ArrayRef::iterator I = Headers.begin(), + E = Headers.end(); + I != E; ++I) { + HeaderList.push_back(getCanonicalPath(*I)); + } + } + ~PreprocessorTrackerImpl() {} // Handle entering a preprocessing session. @@ -889,6 +899,10 @@ public: // "namespace {}" blocks containing #include directives. void handleIncludeDirective(llvm::StringRef DirectivePath, int DirectiveLine, int DirectiveColumn, llvm::StringRef TargetPath) { + // If it's not a header in the header list, ignore it with respect to + // the check. + if (BlockCheckHeaderListOnly && !isHeaderListHeader(DirectivePath)) + return; HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath); StringHandle IncludeHeaderHandle = addString(TargetPath); for (std::vector::const_iterator I = IncludeDirectives.begin(), @@ -959,6 +973,7 @@ public: if (!InNestedHeader) InNestedHeader = !HeadersInThisCompile.insert(H).second; } + // Handle exiting a header source file. void handleHeaderExit(llvm::StringRef HeaderPath) { // Ignore and to reduce message clutter. @@ -982,6 +997,18 @@ public: return CanonicalPath; } + // Return true if the given header is in the header list. + bool isHeaderListHeader(llvm::StringRef HeaderPath) const { + std::string CanonicalPath = getCanonicalPath(HeaderPath); + for (llvm::ArrayRef::iterator I = HeaderList.begin(), + E = HeaderList.end(); + I != E; ++I) { + if (*I == CanonicalPath) + return true; + } + return false; + } + // Get the handle of a header file entry. // Return HeaderHandleInvalid if not found. HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const { @@ -1301,6 +1328,9 @@ public: } private: + llvm::SmallVector HeaderList; + // Only do extern, namespace check for headers in HeaderList. + bool BlockCheckHeaderListOnly; llvm::StringPool Strings; std::vector HeaderPaths; std::vector HeaderStack; @@ -1319,8 +1349,10 @@ private: PreprocessorTracker::~PreprocessorTracker() {} // Create instance of PreprocessorTracker. -PreprocessorTracker *PreprocessorTracker::create() { - return new PreprocessorTrackerImpl(); +PreprocessorTracker *PreprocessorTracker::create( + llvm::SmallVector &Headers, + bool DoBlockCheckHeaderListOnly) { + return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly); } // Preprocessor callbacks for modularize. diff --git a/clang-tools-extra/modularize/PreprocessorTracker.h b/clang-tools-extra/modularize/PreprocessorTracker.h index 4f72d0146317..a283d9f2f8f3 100644 --- a/clang-tools-extra/modularize/PreprocessorTracker.h +++ b/clang-tools-extra/modularize/PreprocessorTracker.h @@ -77,7 +77,9 @@ public: virtual bool reportInconsistentConditionals(llvm::raw_ostream &OS) = 0; // Create instance of PreprocessorTracker. - static PreprocessorTracker *create(); + static PreprocessorTracker *create( + llvm::SmallVector &Headers, + bool DoBlockCheckHeaderListOnly); }; } // end namespace Modularize diff --git a/clang-tools-extra/test/modularize/NoProblemsNamespace.modularize b/clang-tools-extra/test/modularize/NoProblemsNamespace.modularize new file mode 100644 index 000000000000..1c3f78d069a5 --- /dev/null +++ b/clang-tools-extra/test/modularize/NoProblemsNamespace.modularize @@ -0,0 +1,3 @@ +# RUN: modularize -block-check-header-list-only + +Inputs/IncludeInNamespace.h