diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaModule.cpp | 11 |
4 files changed, 52 insertions, 1 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 1d27f74..0410032 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1251,6 +1251,33 @@ void Sema::ActOnEndOfTranslationUnit() { emitAndClearUnusedLocalTypedefWarnings(); } + // C++ standard modules. Diagnose cases where a function is declared inline + // in the module purview but has no definition before the end of the TU or + // the start of a Private Module Fragment (if one is present). + if (!PendingInlineFuncDecls.empty()) { + for (auto *D : PendingInlineFuncDecls) { + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + bool DefInPMF = false; + if (auto *FDD = FD->getDefinition()) { + assert(FDD->getOwningModule() && + FDD->getOwningModule()->isModulePurview()); + DefInPMF = FDD->getOwningModule()->isPrivateModule(); + if (!DefInPMF) + continue; + } + Diag(FD->getLocation(), diag::err_export_inline_not_defined) + << DefInPMF; + // If we have a PMF it should be at the end of the ModuleScopes. + if (DefInPMF && + ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment) { + Diag(ModuleScopes.back().BeginLoc, + diag::note_private_module_fragment); + } + } + } + PendingInlineFuncDecls.clear(); + } + // C99 6.9.2p2: // A declaration of an identifier for an object that has file // scope without an initializer, and without a storage-class diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 33b4948..004c1ff 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9838,6 +9838,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setType(Context.getFunctionType( FPT->getReturnType(), FPT->getParamTypes(), FPT->getExtProtoInfo().withExceptionSpec(EST_BasicNoexcept))); + + // C++20 [dcl.inline]/7 + // If an inline function or variable that is attached to a named module + // is declared in a definition domain, it shall be defined in that + // domain. + // So, if the current declaration does not have a definition, we must + // check at the end of the TU (or when the PMF starts) to see that we + // have a definition at that point. + if (isInline && !D.isFunctionDefinition() && getLangOpts().CPlusPlus20 && + NewFD->hasOwningModule() && + NewFD->getOwningModule()->isModulePurview()) { + PendingInlineFuncDecls.insert(NewFD); + } } // Filter out previous declarations that don't match the scope. diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 1d8df94..22d72c3 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -5691,7 +5691,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, llvm::SmallVector<Module*, 8> UniqueModules; llvm::SmallDenseSet<Module*, 8> UniqueModuleSet; for (auto *M : Modules) { - if (M->Kind == Module::GlobalModuleFragment) + if (M->isGlobalModule() || M->isPrivateModule()) continue; if (UniqueModuleSet.insert(M).second) UniqueModules.push_back(M); diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 757c611..b205fd9 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -910,6 +910,17 @@ Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) { diagExportedUnnamedDecl(*this, UnnamedDeclKind::Context, Child, BlockStart); } + if (auto *FD = dyn_cast<FunctionDecl>(Child)) { + // [dcl.inline]/7 + // If an inline function or variable that is attached to a named module + // is declared in a definition domain, it shall be defined in that + // domain. + // So, if the current declaration does not have a definition, we must + // check at the end of the TU (or when the PMF starts) to see that we + // have a definition at that point. + if (FD->isInlineSpecified() && !FD->isDefined()) + PendingInlineFuncDecls.insert(FD); + } } } |