summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-02-04 23:37:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-02-04 23:37:59 +0000
commit4eca9b93720b8f5746159eed43a0b3c0bf496db0 (patch)
tree6bef588cf2e4f659f1dc6daf772ec5b19b14e43e
parent712d5c393b7d5d336e60b528788e3f2e46bb8777 (diff)
downloadbcm5719-llvm-4eca9b93720b8f5746159eed43a0b3c0bf496db0.tar.gz
bcm5719-llvm-4eca9b93720b8f5746159eed43a0b3c0bf496db0.zip
[modules] When using -E, we may try to merge decls despite having no Sema
object. In such a case, use the TU's DC for merging global decls rather than giving up when we find there is no TU scope. Ultimately, we should probably avoid all loading of decls when preprocessing, but there are other reasonable use cases for loading an AST file with no Sema object for which this is the right thing. llvm-svn: 228234
-rw-r--r--clang/include/clang/Frontend/CompilerInstance.h2
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp27
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp5
-rw-r--r--clang/test/Modules/Inputs/preprocess/file.h3
-rw-r--r--clang/test/Modules/Inputs/preprocess/fwd.h1
-rw-r--r--clang/test/Modules/Inputs/preprocess/module.modulemap2
-rw-r--r--clang/test/Modules/preprocess.m12
7 files changed, 34 insertions, 18 deletions
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 0f49b346107..e0996d40f31 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -588,7 +588,7 @@ public:
/// Create an external AST source to read a PCH file.
///
/// \return - The new object on success, or null on failure.
- static ExternalASTSource *createPCHExternalASTSource(
+ static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
void *DeserializationListener, bool OwnDeserializationListener,
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 041a1e95225..9cb26f86c79 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -388,32 +388,30 @@ void CompilerInstance::createASTContext() {
void CompilerInstance::createPCHExternalASTSource(
StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors,
void *DeserializationListener, bool OwnDeserializationListener) {
- IntrusiveRefCntPtr<ExternalASTSource> Source;
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
- Source = createPCHExternalASTSource(
+ ModuleManager = createPCHExternalASTSource(
Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),
DeserializationListener, OwnDeserializationListener, Preamble,
getFrontendOpts().UseGlobalModuleIndex);
- ModuleManager = static_cast<ASTReader*>(Source.get());
- getASTContext().setExternalSource(Source);
}
-ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
+IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
void *DeserializationListener, bool OwnDeserializationListener,
bool Preamble, bool UseGlobalModuleIndex) {
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
- std::unique_ptr<ASTReader> Reader;
- Reader.reset(new ASTReader(PP, Context,
- Sysroot.empty() ? "" : Sysroot.c_str(),
- DisablePCHValidation,
- AllowPCHWithCompilerErrors,
- /*AllowConfigurationMismatch*/false,
- HSOpts.ModulesValidateSystemHeaders,
- UseGlobalModuleIndex));
+ IntrusiveRefCntPtr<ASTReader> Reader(
+ new ASTReader(PP, Context, Sysroot.empty() ? "" : Sysroot.c_str(),
+ DisablePCHValidation, AllowPCHWithCompilerErrors,
+ /*AllowConfigurationMismatch*/ false,
+ HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex));
+
+ // We need the external source to be set up before we read the AST, because
+ // eagerly-deserialized declarations may use it.
+ Context.setExternalSource(Reader.get());
Reader->setDeserializationListener(
static_cast<ASTDeserializationListener *>(DeserializationListener),
@@ -427,7 +425,7 @@ ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
// Set the predefines buffer as suggested by the PCH reader. Typically, the
// predefines buffer will be empty.
PP.setPredefines(Reader->getSuggestedPredefines());
- return Reader.release();
+ return Reader;
case ASTReader::Failure:
// Unrecoverable failure: don't even try to process the input file.
@@ -442,6 +440,7 @@ ExternalASTSource *CompilerInstance::createPCHExternalASTSource(
break;
}
+ Context.setExternalSource(nullptr);
return nullptr;
}
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 87b5296c946..56506073af2 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2591,6 +2591,11 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
: nullptr;
+ // We can see the TU here only if we have no Sema object. In that case,
+ // there's no TU scope to look in, so using the DC alone is sufficient.
+ if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
+ return TU;
+
return nullptr;
}
diff --git a/clang/test/Modules/Inputs/preprocess/file.h b/clang/test/Modules/Inputs/preprocess/file.h
new file mode 100644
index 00000000000..808ade5768b
--- /dev/null
+++ b/clang/test/Modules/Inputs/preprocess/file.h
@@ -0,0 +1,3 @@
+struct __FILE;
+#include "fwd.h"
+typedef struct __FILE FILE;
diff --git a/clang/test/Modules/Inputs/preprocess/fwd.h b/clang/test/Modules/Inputs/preprocess/fwd.h
new file mode 100644
index 00000000000..4a19c6d0c05
--- /dev/null
+++ b/clang/test/Modules/Inputs/preprocess/fwd.h
@@ -0,0 +1 @@
+struct __FILE;
diff --git a/clang/test/Modules/Inputs/preprocess/module.modulemap b/clang/test/Modules/Inputs/preprocess/module.modulemap
new file mode 100644
index 00000000000..a5c5b61dddc
--- /dev/null
+++ b/clang/test/Modules/Inputs/preprocess/module.modulemap
@@ -0,0 +1,2 @@
+module fwd { header "fwd.h" export * }
+module file { header "file.h" export * }
diff --git a/clang/test/Modules/preprocess.m b/clang/test/Modules/preprocess.m
index 5c32997f62f..9b563fef821 100644
--- a/clang/test/Modules/preprocess.m
+++ b/clang/test/Modules/preprocess.m
@@ -1,9 +1,14 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -include %S/Inputs/preprocess-prefix.h -E %s | FileCheck -strict-whitespace %s
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -x objective-c-header -emit-pch %S/Inputs/preprocess-prefix.h -o %t.pch
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -include-pch %t.pch -E %s | FileCheck -strict-whitespace %s
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -I %S/Inputs/preprocess -include %S/Inputs/preprocess-prefix.h -E %s | FileCheck -strict-whitespace %s
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -I %S/Inputs/preprocess -x objective-c-header -emit-pch %S/Inputs/preprocess-prefix.h -o %t.pch
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -I %S/Inputs/preprocess -include-pch %t.pch -E %s | FileCheck -strict-whitespace %s
+//
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -I %S/Inputs/preprocess -x objective-c++ -include %S/Inputs/preprocess-prefix.h -E %s | FileCheck -strict-whitespace %s
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -I %S/Inputs/preprocess -x objective-c++-header -emit-pch %S/Inputs/preprocess-prefix.h -o %t.pch
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs -I %S/Inputs/preprocess -x objective-c++ -include-pch %t.pch -E %s | FileCheck -strict-whitespace %s
#import "diamond_right.h"
#import "diamond_right.h" // to check that imports get their own line
+#include "file.h"
void test() {
top_left_before();
left_and_right();
@@ -15,6 +20,7 @@ void test() {
// CHECK: @import diamond_right; /* clang -E: implicit import for "{{.*}}diamond_right.h" */{{$}}
// CHECK: @import diamond_right; /* clang -E: implicit import for "{{.*}}diamond_right.h" */{{$}}
+// CHECK: @import file; /* clang -E: implicit import for "{{.*}}file.h" */{{$}}
// CHECK-NEXT: void test() {{{$}}
// CHECK-NEXT: top_left_before();{{$}}
// CHECK-NEXT: left_and_right();{{$}}
OpenPOWER on IntegriCloud