Modules: set SystemHeader to true if we are building a system module.

If we are processing a #include from a module build, we should treat it
as a system header if we're building a system module. Passing an optional
flag to HeaderSearch::LookupFile.

Before this, the testing case will crash when accessing a freed FileEntry.

rdar://26214027


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269730 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manman Ren 2016-05-17 02:15:12 +00:00
parent 24f1d22d44
commit c760a821c1
8 changed files with 44 additions and 7 deletions

View File

@ -381,7 +381,7 @@ public:
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
bool SkipCache = false, bool BuildSystemModule = false);
/// \brief Look up a subframework for the specified \#include file.
///

View File

@ -565,7 +565,7 @@ const FileEntry *HeaderSearch::LookupFile(
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache) {
bool SkipCache, bool BuildSystemModule) {
if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader();
@ -613,11 +613,12 @@ const FileEntry *HeaderSearch::LookupFile(
// getFileAndSuggestModule, because it's a reference to an element of
// a container that could be reallocated across this call.
//
// FIXME: If we have no includer, that means we're processing a #include
// If we have no includer, that means we're processing a #include
// from a module build. We should treat this as a system header if we're
// building a [system] module.
bool IncluderIsSystemHeader =
Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User;
(Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User) ||
(!Includer && BuildSystemModule);
if (const FileEntry *FE = getFileAndSuggestModule(
TmpDir, IncluderAndDir.second, IncluderIsSystemHeader,
RequestingModule, SuggestedModule)) {

View File

@ -671,6 +671,7 @@ const FileEntry *Preprocessor::LookupFile(
// stack, record the parent #includes.
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
Includers;
bool BuildSystemModule = false;
if (!FromDir && !FromFile) {
FileID FID = getCurrentFileLexer()->getFileID();
const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID);
@ -688,9 +689,10 @@ const FileEntry *Preprocessor::LookupFile(
// come from header declarations in the module map) relative to the module
// map file.
if (!FileEnt) {
if (FID == SourceMgr.getMainFileID() && MainFileDir)
if (FID == SourceMgr.getMainFileID() && MainFileDir) {
Includers.push_back(std::make_pair(nullptr, MainFileDir));
else if ((FileEnt =
BuildSystemModule = getCurrentModule()->IsSystem;
} else if ((FileEnt =
SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())))
Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory(".")));
} else {
@ -736,7 +738,8 @@ const FileEntry *Preprocessor::LookupFile(
// Do a standard file entry lookup.
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
RelativePath, RequestingModule, SuggestedModule, SkipCache);
RelativePath, RequestingModule, SuggestedModule, SkipCache,
BuildSystemModule);
if (FE) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(

View File

@ -0,0 +1 @@
@import UseAfterFreePublic;

View File

@ -0,0 +1,2 @@
@interface S1
@end

View File

@ -0,0 +1,3 @@
module UseAfterFreePublic {
header "UseAfterFreePublic.h"
}

View File

@ -0,0 +1,3 @@
module UseAfterFreePrivate {
header "UseAfterFreePrivate.h"
}

View File

@ -0,0 +1,24 @@
// RUN: rm -rf %t
// Here, we build the module without "non-modular-include-in-framework-module".
// RUN: echo '@import UseAfterFreePublic;' | \
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t -isystem %S/Inputs/UseAfterFree/ -fsyntax-only \
// RUN: -x objective-c -
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t -isystem %S/Inputs/UseAfterFree/ -fsyntax-only \
// RUN: -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module \
// RUN: -x objective-c %s -verify
// expected-no-diagnostics
// Here, we load the module UseAfterFreePublic, it is treated as a system module,
// we ignore the inconsistency for "non-modular-include-in-framework-module".
@import UseAfterFreePublic;
// We start a thread to build the module for UseAfterFreePrivate.h. In the thread,
// we load UseAfterFreePublic and should treat it as a system module as well.
// If not, we will invalidate UseAfterFreePublic because of the inconsistency
// for "non-modular-include-in-framework-module", and have a use-after-free error
// of the FileEntry.
#import <UseAfterFreePrivate.h>