diff options
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 114 |
1 files changed, 68 insertions, 46 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index befe6ac7630..d09658060b0 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -857,20 +857,13 @@ void Sema::ActOnStartOfTranslationUnit() { } } -/// ActOnEndOfTranslationUnit - This is called at the very end of the -/// translation unit when EOF is reached and all but the top-level scope is -/// popped. -void Sema::ActOnEndOfTranslationUnit() { - assert(DelayedDiagnostics.getCurrentPool() == nullptr - && "reached end of translation unit with a pool attached?"); - - // If code completion is enabled, don't perform any end-of-translation-unit - // work. - if (PP.isCodeCompletionEnabled()) +void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) { + // No explicit actions are required at the end of the global module fragment. + if (Kind == TUFragmentKind::Global) return; // Transfer late parsed template instantiations over to the pending template - // instantiation list. During normal compliation, the late template parser + // instantiation list. During normal compilation, the late template parser // will be installed and instantiating these templates will succeed. // // If we are building a TU prefix for serialization, it is also safe to @@ -883,50 +876,79 @@ void Sema::ActOnEndOfTranslationUnit() { LateParsedInstantiations.end()); LateParsedInstantiations.clear(); + // If DefinedUsedVTables ends up marking any virtual member functions it + // might lead to more pending template instantiations, which we then need + // to instantiate. + DefineUsedVTables(); + + // C++: Perform implicit template instantiations. + // + // FIXME: When we perform these implicit instantiations, we do not + // carefully keep track of the point of instantiation (C++ [temp.point]). + // This means that name lookup that occurs within the template + // instantiation will always happen at the end of the translation unit, + // so it will find some names that are not required to be found. This is + // valid, but we could do better by diagnosing if an instantiation uses a + // name that was not visible at its first point of instantiation. + if (ExternalSource) { + // Load pending instantiations from the external source. + SmallVector<PendingImplicitInstantiation, 4> Pending; + ExternalSource->ReadPendingInstantiations(Pending); + for (auto PII : Pending) + if (auto Func = dyn_cast<FunctionDecl>(PII.first)) + Func->setInstantiationIsPending(true); + PendingInstantiations.insert(PendingInstantiations.begin(), + Pending.begin(), Pending.end()); + } + + { + llvm::TimeTraceScope TimeScope("PerformPendingInstantiations", + StringRef("")); + PerformPendingInstantiations(); + } + + assert(LateParsedInstantiations.empty() && + "end of TU template instantiation should not create more " + "late-parsed templates"); +} + +/// ActOnEndOfTranslationUnit - This is called at the very end of the +/// translation unit when EOF is reached and all but the top-level scope is +/// popped. +void Sema::ActOnEndOfTranslationUnit() { + assert(DelayedDiagnostics.getCurrentPool() == nullptr + && "reached end of translation unit with a pool attached?"); + + // If code completion is enabled, don't perform any end-of-translation-unit + // work. + if (PP.isCodeCompletionEnabled()) + return; + // Complete translation units and modules define vtables and perform implicit // instantiations. PCH files do not. if (TUKind != TU_Prefix) { DiagnoseUseOfUnimplementedSelectors(); - // If DefinedUsedVTables ends up marking any virtual member functions it - // might lead to more pending template instantiations, which we then need - // to instantiate. - DefineUsedVTables(); - - // C++: Perform implicit template instantiations. - // - // FIXME: When we perform these implicit instantiations, we do not - // carefully keep track of the point of instantiation (C++ [temp.point]). - // This means that name lookup that occurs within the template - // instantiation will always happen at the end of the translation unit, - // so it will find some names that are not required to be found. This is - // valid, but we could do better by diagnosing if an instantiation uses a - // name that was not visible at its first point of instantiation. - if (ExternalSource) { - // Load pending instantiations from the external source. - SmallVector<PendingImplicitInstantiation, 4> Pending; - ExternalSource->ReadPendingInstantiations(Pending); - for (auto PII : Pending) - if (auto Func = dyn_cast<FunctionDecl>(PII.first)) - Func->setInstantiationIsPending(true); - PendingInstantiations.insert(PendingInstantiations.begin(), - Pending.begin(), Pending.end()); - } - - { - llvm::TimeTraceScope TimeScope("PerformPendingInstantiations", - StringRef("")); - PerformPendingInstantiations(); - } - - assert(LateParsedInstantiations.empty() && - "end of TU template instantiation should not create more " - "late-parsed templates"); + ActOnEndOfTranslationUnitFragment( + !ModuleScopes.empty() && ModuleScopes.back().Module->Kind == + Module::PrivateModuleFragment + ? TUFragmentKind::Private + : TUFragmentKind::Normal); if (LateTemplateParserCleanup) LateTemplateParserCleanup(OpaqueParser); CheckDelayedMemberExceptionSpecs(); + } else { + // If we are building a TU prefix for serialization, it is safe to transfer + // these over, even though they are not parsed. The end of the TU should be + // outside of any eager template instantiation scope, so when this AST is + // deserialized, these templates will not be parsed until the end of the + // combined TU. + PendingInstantiations.insert(PendingInstantiations.end(), + LateParsedInstantiations.begin(), + LateParsedInstantiations.end()); + LateParsedInstantiations.clear(); } DiagnoseUnterminatedPragmaPack(); @@ -1000,7 +1022,7 @@ void Sema::ActOnEndOfTranslationUnit() { if (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface && (ModuleScopes.empty() || - ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) && + !ModuleScopes.back().Module->isModulePurview()) && !DiagnosedMissingModuleDeclaration) { // FIXME: Make a better guess as to where to put the module declaration. Diag(getSourceManager().getLocForStartOfFile( |