diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-13 20:27:03 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-13 20:27:03 +0000 |
commit | f122a138e39dbb29162abfa9a3d44091d8efa7af (patch) | |
tree | 08459273e5a9442d2471a8f499d76c58341011bd | |
parent | 8ab09da1faaa33b9fa78de59cc4e191bfe9907b5 (diff) |
Add -isystem-prefix and -ino-system-prefix arguments, which can be used to
override whether headers are system headers by checking for prefixes of the
header name specified in the #include directive.
This allows warnings to be disabled for third-party code which is found in
specific subdirectories of include paths.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158418 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/UsersManual.html | 40 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 8 | ||||
-rw-r--r-- | include/clang/Frontend/HeaderSearchOptions.h | 22 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 12 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 18 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 13 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 10 | ||||
-rw-r--r-- | test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/all.h | 1 | ||||
-rw-r--r-- | test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/warn.h | 2 | ||||
-rw-r--r-- | test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/all.h | 1 | ||||
-rw-r--r-- | test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/warn.h | 2 | ||||
-rw-r--r-- | test/Frontend/Inputs/SystemHeaderPrefix/src/all.h | 6 | ||||
-rw-r--r-- | test/Frontend/Inputs/SystemHeaderPrefix/src/warn.h | 2 | ||||
-rw-r--r-- | test/Frontend/system-header-prefix.c | 11 |
14 files changed, 148 insertions, 0 deletions
diff --git a/docs/UsersManual.html b/docs/UsersManual.html index 2356b03146..a0e5ed8e8c 100644 --- a/docs/UsersManual.html +++ b/docs/UsersManual.html @@ -43,6 +43,7 @@ td { <li><a href="#diagnostics_categories">Diagnostic Categories</a></li> <li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li> <li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li> + <li><a href="#diagnostics_systemheader">Controlling Diagnostics in System Headers</a></li> <li><a href="#diagnostics_enable_everything">Enabling All Warnings</a></li> <li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li> </ul> @@ -654,6 +655,45 @@ GCC do not support the exact same set of warnings, so even when using GCC compatible #pragmas there is no guarantee that they will have identical behaviour on both compilers. </p> +<h4 id="diagnostics_systemheader">Controlling Diagnostics in System Headers</h4> + +<p>Warnings are suppressed when they occur in system headers. By default, an +included file is treated as a system header if it is found in an include path +specified by <tt>-isystem</tt>, but this can be overridden in several ways.</p> + +<p>The <tt>system_header</tt> pragma can be used to mark the current file as +being a system header. No warnings will be produced from the location of the +pragma onwards within the same file.</p> + +<pre> +char a = 'xy'; // warning + +#pragma clang system_header + +char b = 'ab'; // no warning +</pre> + +<p>The <tt>-isystem-prefix</tt> and <tt>-ino-system-prefix</tt> command-line +arguments can be used to override whether subsets of an include path are treated +as system headers. When the name in a <tt>#include</tt> directive is found +within a header search path and starts with a system prefix, the header is +treated as a system header. The last prefix on the command-line which matches +the specified header name takes precedence. For instance:</p> + +<pre> +clang -Ifoo -isystem bar -isystem-prefix x/ -ino-system-prefix x/y/ +</pre> + +<p>Here, <tt>#include "x/a.h"</tt> is treated as including a system header, even +if the header is found in <tt>foo</tt>, and <tt>#include "x/y/b.h"</tt> is +treated as not including a system header, even if the header is found in +<tt>bar</tt>. +</p> + +<p>A <tt>#include</tt> directive which finds a file relative to the current +directory is treated as including a system header if the including file is +treated as a system header.</p> + <h4 id="diagnostics_enable_everything">Enabling All Warnings</h4> <p>In addition to the traditional <tt>-W</tt> flags, one can enable <b>all</b> diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index b4aba8d31b..20b8c58f0d 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -471,6 +471,14 @@ def internal_externc_isystem : JoinedOrSeparate<"-internal-externc-isystem">, "implicit extern \"C\" semantics; these are assumed to not be " "user-provided and are used to model system and standard headers' " "paths.">; +def isystem_prefix : JoinedOrSeparate<"-isystem-prefix">, + MetaVarName<"<prefix>">, + HelpText<"Treat all #include paths starting with <prefix> as including a " + "system header.">; +def ino_system_prefix : JoinedOrSeparate<"-ino-system-prefix">, + MetaVarName<"<prefix>">, + HelpText<"Treat all #include paths starting with <prefix> as not including a " + "system header.">; //===----------------------------------------------------------------------===// // Preprocessor Options diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 687f439fe1..bdd26232c0 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -69,6 +69,18 @@ public: IsInternal(isInternal), ImplicitExternC(implicitExternC) {} }; + struct SystemHeaderPrefix { + /// A prefix to be matched against paths in #include directives. + std::string Prefix; + + /// True if paths beginning with this prefix should be treated as system + /// headers. + bool IsSystemHeader; + + SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) + : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} + }; + /// If non-empty, the directory to use as a "virtual system root" for include /// paths. std::string Sysroot; @@ -76,6 +88,9 @@ public: /// User specified include entries. std::vector<Entry> UserEntries; + /// User-specified system header prefixes. + std::vector<SystemHeaderPrefix> SystemHeaderPrefixes; + /// The directory which holds the compiler resource files (builtin includes, /// etc.). std::string ResourceDir; @@ -117,6 +132,13 @@ public: UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, IgnoreSysRoot, IsInternal, ImplicitExternC)); } + + /// AddSystemHeaderPrefix - Override whether #include directives naming a + /// path starting with \arg Prefix should be considered as naming a system + /// header. + void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { + SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader)); + } }; } // end namespace clang diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 5128ce6c11..e087e7190e 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -16,6 +16,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleMap.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" @@ -144,6 +145,12 @@ class HeaderSearch { unsigned SystemDirIdx; bool NoCurDirSearch; + /// #include prefixes for which the 'system header' property is overridden. + /// For a #include "x" or #include <x> directive, the last string in this + /// list which is a prefix of 'x' determines whether the file is treated as + /// a system header. + std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes; + /// \brief The path to the module cache. std::string ModuleCachePath; @@ -235,6 +242,11 @@ public: SystemDirIdx++; } + /// SetSystemHeaderPrefixes - Set the list of system header prefixes. + void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) { + SystemHeaderPrefixes.assign(P.begin(), P.end()); + } + /// HasIncludeAliasMap - Checks whether the map exists or not bool HasIncludeAliasMap() const { return IncludeAliases; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 99c338c876..81d78c0e65 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -624,6 +624,16 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, Res.push_back(E.Path); } + /// User-specified system header prefixes. + for (unsigned i = 0, e = Opts.SystemHeaderPrefixes.size(); i != e; ++i) { + if (Opts.SystemHeaderPrefixes[i].IsSystemHeader) + Res.push_back("-isystem-prefix"); + else + Res.push_back("-ino-system-prefix"); + + Res.push_back(Opts.SystemHeaderPrefixes[i].Prefix); + } + if (!Opts.ResourceDir.empty()) Res.push_back("-resource-dir", Opts.ResourceDir); if (!Opts.ModuleCachePath.empty()) @@ -1688,6 +1698,14 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.AddPath((*I)->getValue(Args), frontend::System, false, false, /*IgnoreSysRoot=*/true, /*IsInternal=*/true, (*I)->getOption().matches(OPT_internal_externc_isystem)); + + // Add the path prefixes which are implicitly treated as being system headers. + for (arg_iterator I = Args.filtered_begin(OPT_isystem_prefix, + OPT_ino_system_prefix), + E = Args.filtered_end(); + I != E; ++I) + Opts.AddSystemHeaderPrefix((*I)->getValue(Args), + (*I)->getOption().matches(OPT_isystem_prefix)); } void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 3f7e682514..e5a8ca48cf 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -40,6 +40,7 @@ class InitHeaderSearch { std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath; typedef std::vector<std::pair<IncludeDirGroup, DirectoryLookup> >::const_iterator path_iterator; + std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes; HeaderSearch &Headers; bool Verbose; std::string IncludeSysroot; @@ -57,6 +58,12 @@ public: bool isCXXAware, bool isUserSupplied, bool isFramework, bool IgnoreSysRoot = false); + /// AddSystemHeaderPrefix - Add the specified prefix to the system header + /// prefix list. + void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { + SystemHeaderPrefixes.push_back(std::make_pair(Prefix, IsSystemHeader)); + } + /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu /// libstdc++. void AddGnuCPlusPlusIncludePaths(StringRef Base, @@ -623,6 +630,8 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) { bool DontSearchCurDir = false; // TODO: set to true if -I- is set? Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir); + Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes); + // If verbose, print the list of directories that will be searched. if (Verbose) { llvm::errs() << "#include \"...\" search starts here:\n"; @@ -660,6 +669,10 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, Init.AddDefaultIncludePaths(Lang, Triple, HSOpts); + for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i) + Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix, + HSOpts.SystemHeaderPrefixes[i].IsSystemHeader); + if (HSOpts.UseBuiltinIncludes) { // Set up the builtin include directory in the module map. llvm::sys::Path P(HSOpts.ResourceDir); diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index d688e23fa4..4531335b75 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -510,6 +510,16 @@ const FileEntry *HeaderSearch::LookupFile( if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework) HFI.DirInfo = SrcMgr::C_System; + // If the filename matches a known system header prefix, override + // whether the file is a system header. + for (unsigned i = SystemHeaderPrefixes.size(); i; --i) { + if (Filename.startswith(SystemHeaderPrefixes[i-1].first)) { + HFI.DirInfo = SystemHeaderPrefixes[i-1].second ? SrcMgr::C_System + : SrcMgr::C_User; + break; + } + } + // If this file is found in a header map and uses the framework style of // includes, then this header is part of a framework we're building. if (CurDir->isIndexHeaderMap()) { diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/all.h b/test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/all.h new file mode 100644 index 0000000000..0f3f0be3c7 --- /dev/null +++ b/test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/all.h @@ -0,0 +1 @@ +#include "warn.h" diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/warn.h b/test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/warn.h new file mode 100644 index 0000000000..def881aa13 --- /dev/null +++ b/test/Frontend/Inputs/SystemHeaderPrefix/libs/boost/warn.h @@ -0,0 +1,2 @@ +#if BOOST +#endif diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/all.h b/test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/all.h new file mode 100644 index 0000000000..0f3f0be3c7 --- /dev/null +++ b/test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/all.h @@ -0,0 +1 @@ +#include "warn.h" diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/warn.h b/test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/warn.h new file mode 100644 index 0000000000..6a0c102ea4 --- /dev/null +++ b/test/Frontend/Inputs/SystemHeaderPrefix/libs/mylib/warn.h @@ -0,0 +1,2 @@ +#if MYLIB +#endif diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/src/all.h b/test/Frontend/Inputs/SystemHeaderPrefix/src/all.h new file mode 100644 index 0000000000..ace9699f85 --- /dev/null +++ b/test/Frontend/Inputs/SystemHeaderPrefix/src/all.h @@ -0,0 +1,6 @@ +#include "libs/boost/all.h" +#include "libs/mylib/all.h" + +#include "libs/boost/warn.h" +#include "libs/mylib/warn.h" +#include "src/warn.h" diff --git a/test/Frontend/Inputs/SystemHeaderPrefix/src/warn.h b/test/Frontend/Inputs/SystemHeaderPrefix/src/warn.h new file mode 100644 index 0000000000..91e2591855 --- /dev/null +++ b/test/Frontend/Inputs/SystemHeaderPrefix/src/warn.h @@ -0,0 +1,2 @@ +#if SRC +#endif diff --git a/test/Frontend/system-header-prefix.c b/test/Frontend/system-header-prefix.c new file mode 100644 index 0000000000..31194d96e5 --- /dev/null +++ b/test/Frontend/system-header-prefix.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -isystem-prefix libs/ -ino-system-prefix libs/mylib/ -I%S/Inputs/SystemHeaderPrefix -Wundef -E %s 2>&1 | FileCheck %s + +#include "src/all.h" + +// CHECK-NOT: BOOST +// CHECK: libs/mylib/warn.h:1:5: warning: 'MYLIB' is not defined, evaluates to 0 +// CHECK-NOT: BOOST +// CHECK: libs/mylib/warn.h:1:5: warning: 'MYLIB' is not defined, evaluates to 0 +// CHECK-NOT: BOOST +// CHECK: src/warn.h:1:5: warning: 'SRC' is not defined, evaluates to 0 +// CHECK-NOT: BOOST |