Permalink
Browse files

[Lex] Add support for 'user specified system frameworks' (see test ca…

…se).

 - Developers of system frameworks need a way for their framework to be treated as a "system framework" during development. Otherwise, they are unable to properly test how their framework behaves when installed because of the semantic changes (in warning behavior) applied to system frameworks.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154105 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information...
1 parent 9ee35f9 commit 85ff9693b178658f9d8af7be30a086fb1ab81fdd @ddunbar ddunbar committed Apr 5, 2012
@@ -30,6 +30,7 @@
<li><a href="#vectors">Vectors and Extended Vectors</a></li>
<li><a href="#deprecated">Messages on <tt>deprecated</tt> and <tt>unavailable</tt> attributes</a></li>
<li><a href="#attributes-on-enumerators">Attributes on enumerators</a></li>
+<li><a href="#user_specified_system_framework">'User-Specified' System Frameworks</a></li>
<li><a href="#availability">Availability attribute</a></li>
<li><a href="#checking_language_features">Checks for Standard Language Features</a>
<ul>
@@ -626,6 +627,34 @@ <h2 id="attributes-on-enumerators">Attributes on Enumerators</h2>
<p>Query for this feature with <tt>__has_extension(enumerator_attributes)</tt>.</p>
<!-- ======================================================================= -->
+<h2 id="user_specified_system_framework">'User-Specified' System Frameworks</h2>
+<!-- ======================================================================= -->
+
+<p>Clang provides a mechanism by which frameworks can be built in such a way
+that they will always be treated as being 'system frameworks', even if they are
+not present in a system framework directory. This can be useful to system
+framework developers who want to be able to test building other applications
+with development builds of their framework, including the manner in which the
+compiler changes warning behavior for system headers.</p>
+
+<p>Framework developers can opt-in to this mechanism by creating a
+'.system_framework' file at the top-level of their framework. That is, the
+framework should have contents like:</p>
+
+<pre>
+ .../TestFramework.framework
+ .../TestFramework.framework/.system_framework
+ .../TestFramework.framework/Headers
+ .../TestFramework.framework/Headers/TestFramework.h
+ ...
+</pre>
+
+<p>Clang will treat the presence of this file as an indicator that the framework
+should be treated as a system framework, regardless of how it was found in the
+framework search path. For consistency, we recommend that such files never be
+included in installed versions of the framework.</p>
+
+<!-- ======================================================================= -->
<h2 id="availability">Availability attribute</h2
<!-- ======================================================================= -->
@@ -145,17 +145,23 @@ class DirectoryLookup {
/// \param SuggestedModule If non-null, and the file found is semantically
/// part of a known module, this will be set to the module that should
/// be imported instead of preprocessing/parsing the file found.
+ ///
+ /// \param InUserSpecifiedSystemHeader [out] If the file is found, set to true
+ /// if the file is located in a framework that has been user-specified to be
+ /// treated as a system framework.
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule) const;
+ Module **SuggestedModule,
+ bool &InUserSpecifiedSystemHeader) const;
private:
const FileEntry *DoFrameworkLookup(
StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule) const;
+ Module **SuggestedModule,
+ bool &InUserSpecifiedSystemHeader) const;
};
@@ -124,6 +124,11 @@ class HeaderSearch {
struct FrameworkCacheEntry {
/// The directory entry which should be used for the cached framework.
const DirectoryEntry *Directory;
+
+ /// Whether this framework has been "user-specified" to be treated as if it
+ /// were a system framework (even if it was found outside a system framework
+ /// directory).
+ bool IsUserSpecifiedSystemFramework;
};
FileManager &FileMgr;
@@ -204,7 +204,10 @@ const FileEntry *DirectoryLookup::LookupFile(
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule) const {
+ Module **SuggestedModule,
+ bool &InUserSpecifiedSystemFramework) const {
+ InUserSpecifiedSystemFramework = false;
+
SmallString<1024> TmpDir;
if (isNormalDir()) {
// Concatenate the requested file onto the directory.
@@ -239,7 +242,7 @@ const FileEntry *DirectoryLookup::LookupFile(
if (isFramework())
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
- SuggestedModule);
+ SuggestedModule, InUserSpecifiedSystemFramework);
assert(isHeaderMap() && "Unknown directory lookup");
const FileEntry * const Result = getHeaderMap()->LookupFile(
@@ -266,7 +269,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule) const
+ Module **SuggestedModule,
+ bool &InUserSpecifiedSystemFramework) const
{
FileManager &FileMgr = HS.getFileMgr();
@@ -303,15 +307,27 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
HS.IncrementFrameworkLookupCount();
// If the framework dir doesn't exist, we fail.
- // FIXME: It's probably more efficient to query this with FileMgr.getDir.
- if (!llvm::sys::fs::exists(FrameworkName.str()))
- return 0;
+ const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
+ if (Dir == 0) return 0;
// Otherwise, if it does, remember that this is the right direntry for this
// framework.
CacheEntry.Directory = getFrameworkDir();
+
+ // If this is a user search directory, check if the framework has been
+ // user-specified as a system framework.
+ if (getDirCharacteristic() == SrcMgr::C_User) {
+ SmallString<1024> SystemFrameworkMarker(FrameworkName);
+ SystemFrameworkMarker += ".system_framework";
+ if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
+ CacheEntry.IsUserSpecifiedSystemFramework = true;
+ }
+ }
}
+ // Set the 'user-specified system framework' flag.
+ InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
+
if (RelativePath != NULL) {
RelativePath->clear();
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
@@ -476,9 +492,10 @@ const FileEntry *HeaderSearch::LookupFile(
// Check each directory in sequence to see if it contains this file.
for (; i != SearchDirs.size(); ++i) {
+ bool InUserSpecifiedSystemFramework = false;
const FileEntry *FE =
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
- SuggestedModule);
+ SuggestedModule, InUserSpecifiedSystemFramework);
if (!FE) continue;
CurDir = &SearchDirs[i];
@@ -487,6 +504,12 @@ const FileEntry *HeaderSearch::LookupFile(
HeaderFileInfo &HFI = getFileInfo(FE);
HFI.DirInfo = CurDir->getDirCharacteristic();
+ // If the directory characteristic is User but this framework was
+ // user-specified to be treated as a system framework, promote the
+ // characteristic.
+ if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
+ HFI.DirInfo = SrcMgr::C_System;
+
// 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()) {
@@ -0,0 +1,3 @@
+static inline int another_test_framework_func(unsigned a) {
+ return a;
+}
@@ -0,0 +1,6 @@
+// Include a subframework header.
+#include <AnotherTestFramework/AnotherTestFramework.h>
+
+static inline int test_framework_func(unsigned a) {
+ return a;
+}
@@ -0,0 +1,8 @@
+// RUN: %clang -cc1 -fsyntax-only -F %S/Inputs -Wsign-conversion -verify %s
+
+// Check that TestFramework is treated as a system header.
+#include <TestFramework/TestFramework.h>
+
+int f1() {
+ return test_framework_func(1) + another_test_framework_func(2);
+}

0 comments on commit 85ff969

Please sign in to comment.