mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 17:16:07 +00:00
[Lex] Add support for 'user specified system frameworks' (see test case).
- 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. llvm-svn: 154105
This commit is contained in:
parent
17138613b1
commit
3c9bc4dbdb
@ -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>
|
||||
@ -625,6 +626,34 @@ individual enumerators.</p>
|
||||
|
||||
<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 @@ public:
|
||||
/// \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;
|
||||
}
|
8
clang/test/Preprocessor/user_defined_system_framework.c
Normal file
8
clang/test/Preprocessor/user_defined_system_framework.c
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user