mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 00:36:05 +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="#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="#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="#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="#availability">Availability attribute</a></li>
|
||||||
<li><a href="#checking_language_features">Checks for Standard Language Features</a>
|
<li><a href="#checking_language_features">Checks for Standard Language Features</a>
|
||||||
<ul>
|
<ul>
|
||||||
@ -625,6 +626,34 @@ individual enumerators.</p>
|
|||||||
|
|
||||||
<p>Query for this feature with <tt>__has_extension(enumerator_attributes)</tt>.</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
|
<h2 id="availability">Availability attribute</h2
|
||||||
<!-- ======================================================================= -->
|
<!-- ======================================================================= -->
|
||||||
|
@ -145,17 +145,23 @@ public:
|
|||||||
/// \param SuggestedModule If non-null, and the file found is semantically
|
/// \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
|
/// part of a known module, this will be set to the module that should
|
||||||
/// be imported instead of preprocessing/parsing the file found.
|
/// 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,
|
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule) const;
|
Module **SuggestedModule,
|
||||||
|
bool &InUserSpecifiedSystemHeader) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FileEntry *DoFrameworkLookup(
|
const FileEntry *DoFrameworkLookup(
|
||||||
StringRef Filename, HeaderSearch &HS,
|
StringRef Filename, HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule) const;
|
Module **SuggestedModule,
|
||||||
|
bool &InUserSpecifiedSystemHeader) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,6 +124,11 @@ class HeaderSearch {
|
|||||||
struct FrameworkCacheEntry {
|
struct FrameworkCacheEntry {
|
||||||
/// The directory entry which should be used for the cached framework.
|
/// The directory entry which should be used for the cached framework.
|
||||||
const DirectoryEntry *Directory;
|
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;
|
FileManager &FileMgr;
|
||||||
|
@ -204,7 +204,10 @@ const FileEntry *DirectoryLookup::LookupFile(
|
|||||||
HeaderSearch &HS,
|
HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule) const {
|
Module **SuggestedModule,
|
||||||
|
bool &InUserSpecifiedSystemFramework) const {
|
||||||
|
InUserSpecifiedSystemFramework = false;
|
||||||
|
|
||||||
SmallString<1024> TmpDir;
|
SmallString<1024> TmpDir;
|
||||||
if (isNormalDir()) {
|
if (isNormalDir()) {
|
||||||
// Concatenate the requested file onto the directory.
|
// Concatenate the requested file onto the directory.
|
||||||
@ -239,7 +242,7 @@ const FileEntry *DirectoryLookup::LookupFile(
|
|||||||
|
|
||||||
if (isFramework())
|
if (isFramework())
|
||||||
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
|
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
|
||||||
SuggestedModule);
|
SuggestedModule, InUserSpecifiedSystemFramework);
|
||||||
|
|
||||||
assert(isHeaderMap() && "Unknown directory lookup");
|
assert(isHeaderMap() && "Unknown directory lookup");
|
||||||
const FileEntry * const Result = getHeaderMap()->LookupFile(
|
const FileEntry * const Result = getHeaderMap()->LookupFile(
|
||||||
@ -266,7 +269,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
|||||||
HeaderSearch &HS,
|
HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule) const
|
Module **SuggestedModule,
|
||||||
|
bool &InUserSpecifiedSystemFramework) const
|
||||||
{
|
{
|
||||||
FileManager &FileMgr = HS.getFileMgr();
|
FileManager &FileMgr = HS.getFileMgr();
|
||||||
|
|
||||||
@ -303,15 +307,27 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
|||||||
HS.IncrementFrameworkLookupCount();
|
HS.IncrementFrameworkLookupCount();
|
||||||
|
|
||||||
// If the framework dir doesn't exist, we fail.
|
// If the framework dir doesn't exist, we fail.
|
||||||
// FIXME: It's probably more efficient to query this with FileMgr.getDir.
|
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
|
||||||
if (!llvm::sys::fs::exists(FrameworkName.str()))
|
if (Dir == 0) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Otherwise, if it does, remember that this is the right direntry for this
|
// Otherwise, if it does, remember that this is the right direntry for this
|
||||||
// framework.
|
// framework.
|
||||||
CacheEntry.Directory = getFrameworkDir();
|
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) {
|
if (RelativePath != NULL) {
|
||||||
RelativePath->clear();
|
RelativePath->clear();
|
||||||
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
|
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.
|
// Check each directory in sequence to see if it contains this file.
|
||||||
for (; i != SearchDirs.size(); ++i) {
|
for (; i != SearchDirs.size(); ++i) {
|
||||||
|
bool InUserSpecifiedSystemFramework = false;
|
||||||
const FileEntry *FE =
|
const FileEntry *FE =
|
||||||
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
|
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
|
||||||
SuggestedModule);
|
SuggestedModule, InUserSpecifiedSystemFramework);
|
||||||
if (!FE) continue;
|
if (!FE) continue;
|
||||||
|
|
||||||
CurDir = &SearchDirs[i];
|
CurDir = &SearchDirs[i];
|
||||||
@ -487,6 +504,12 @@ const FileEntry *HeaderSearch::LookupFile(
|
|||||||
HeaderFileInfo &HFI = getFileInfo(FE);
|
HeaderFileInfo &HFI = getFileInfo(FE);
|
||||||
HFI.DirInfo = CurDir->getDirCharacteristic();
|
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
|
// 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.
|
// includes, then this header is part of a framework we're building.
|
||||||
if (CurDir->isIndexHeaderMap()) {
|
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