]> granicus.if.org Git - clang/commitdiff
Modules: set SystemHeader to true if we are building a system module.
authorManman Ren <manman.ren@gmail.com>
Tue, 17 May 2016 02:15:12 +0000 (02:15 +0000)
committerManman Ren <manman.ren@gmail.com>
Tue, 17 May 2016 02:15:12 +0000 (02:15 +0000)
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

include/clang/Lex/HeaderSearch.h
lib/Lex/HeaderSearch.cpp
lib/Lex/PPDirectives.cpp
test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h [new file with mode: 0644]
test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h [new file with mode: 0644]
test/Modules/Inputs/UseAfterFree/module.map [new file with mode: 0644]
test/Modules/Inputs/UseAfterFree/module_private.map [new file with mode: 0644]
test/Modules/use-after-free.m [new file with mode: 0644]

index 6d7817f862321356b87d4abb69d2191fcbaad3a0..152258af166944f85c0b687328821a761084815c 100644 (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.
   ///
index 3bb7f8e042889c0b87bd429dff99fc8dd0264be5..e627c786407fbec82430532a25b00da836398ceb 100644 (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)) {
index c33f9aba267f4e0d027dcb99625569ef541f27e9..34adf7fac29ad9045145fa8e976ca2d1da8b138c 100644 (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(
diff --git a/test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h b/test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h
new file mode 100644 (file)
index 0000000..e8ed9fd
--- /dev/null
@@ -0,0 +1 @@
+@import UseAfterFreePublic;
diff --git a/test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h b/test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h
new file mode 100644 (file)
index 0000000..d017b0f
--- /dev/null
@@ -0,0 +1,2 @@
+@interface S1
+@end
diff --git a/test/Modules/Inputs/UseAfterFree/module.map b/test/Modules/Inputs/UseAfterFree/module.map
new file mode 100644 (file)
index 0000000..35c0b3d
--- /dev/null
@@ -0,0 +1,3 @@
+module UseAfterFreePublic {
+  header "UseAfterFreePublic.h"
+}
diff --git a/test/Modules/Inputs/UseAfterFree/module_private.map b/test/Modules/Inputs/UseAfterFree/module_private.map
new file mode 100644 (file)
index 0000000..75eec41
--- /dev/null
@@ -0,0 +1,3 @@
+module UseAfterFreePrivate {
+  header "UseAfterFreePrivate.h"
+}
diff --git a/test/Modules/use-after-free.m b/test/Modules/use-after-free.m
new file mode 100644 (file)
index 0000000..fa72009
--- /dev/null
@@ -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>