From 77b69ff2b5ee64034caca5006b15909155c20c7d Mon Sep 17 00:00:00 2001 From: yronglin Date: Sun, 19 Oct 2025 01:44:05 +0800 Subject: [PATCH] [C++][Modules] Import declaration should in global module fragment, module interface or module implementation Signed-off-by: yronglin --- clang/include/clang/Basic/DiagnosticParseKinds.td | 3 +++ clang/lib/Parse/Parser.cpp | 7 +++++++ clang/lib/Sema/SemaModule.cpp | 2 +- clang/test/CXX/module/cpp.pre/p1.cpp | 10 ++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/module/cpp.pre/p1.cpp diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index e5e071f43fa75..e930d713b07f3 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1814,6 +1814,9 @@ def err_import_in_wrong_fragment : Error< "module%select{| partition}0 imports cannot be in the %select{global|private}1 module fragment">; def err_export_empty : Error<"export declaration cannot be empty">; +def err_import_decl_not_in_module_fragment : Error< + "module import declaration can only appears in " + "global module fragment, module interface or module implementation">; } let CategoryName = "Generics Issue" in { diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index ec01faf446e8d..ecddd93d197a4 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -2486,6 +2486,13 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc, SeenError = false; break; case Sema::ModuleImportState::FirstDecl: + if (getLangOpts().CPlusPlusModules) { + Diag(ImportLoc, diag::err_import_decl_not_in_module_fragment); + Diag(ImportLoc, diag::note_global_module_introducer_missing) + << FixItHint::CreateInsertion(PP.getMainFileFirstPPTokenLoc(), + "module;"); + } + // If we found an import decl as the first declaration, we must be not in // a C++20 module unit or we are in an invalid state. ImportState = Sema::ModuleImportState::NotACXX20Module; diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index a2aa3eaaa7f6d..e525f64f9a7e9 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -342,7 +342,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, Diag(ModuleLoc, diag::err_module_decl_not_at_start); SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc(); Diag(BeginLoc, diag::note_global_module_introducer_missing) - << FixItHint::CreateInsertion(BeginLoc, "module;\n"); + << FixItHint::CreateInsertion(BeginLoc, "module;"); } // C++23 [module.unit]p1: ... The identifiers module and import shall not diff --git a/clang/test/CXX/module/cpp.pre/p1.cpp b/clang/test/CXX/module/cpp.pre/p1.cpp new file mode 100644 index 0000000000000..3ec7556734f65 --- /dev/null +++ b/clang/test/CXX/module/cpp.pre/p1.cpp @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 %t/import_is_first_decl.cpp -fsyntax-only -verify + +//--- import_is_first_decl.cpp +import std; // expected-error {{module import declaration can only appears in global module fragment, module interface or module implementation}} +// expected-note@-1 {{add 'module;' to the start of the file to introduce a global module fragment}} +// expected-error@-2 {{module 'std' not found}}