sepavloff added a comment. Thanks for helpful notes!
There are similar cases in Objective C. Should they be implemented in this patch or separate patch is OK? ================ Comment at: include/clang/Basic/DiagnosticParseKinds.td:1016 @@ -1015,2 +1015,3 @@ "expected ';' after module name">; +def err_missing_before_module_end : Error<"expected %0 at the end of module">; } ---------------- rsmith wrote: > I would drop the "the" in this error. Done. ================ Comment at: include/clang/Basic/DiagnosticSemaKinds.td:7774 @@ -7771,1 +7773,3 @@ "@import of module '%0' in implementation of '%1'; use #import">; +def note_module_need_top_level : Note<"consider moving the import to top level">; +def note_module_need_textual : Note<"consider marking the header as textual">; ---------------- silvas wrote: > rsmith wrote: > > We'll already have said something like: > > > > error: import of module 'foo' appears within class X > > note: class X begins here > > > > There are two likely situations here: either the header was intended to be > > included textually, or the user forgot a `}` or similar and didn't expect > > for the import to be inside the class. Either way, this note is not useful > > (either they thought it *was* at the top level, or the note is not > > applicable). > > > > How about dropping this note? The "begins here" note seems to have already > > covered the interesting case. > I think this makes sense. `error: ... import ... appears within ...` seems > like sufficient information about the nature of the error. The message is removed. ================ Comment at: include/clang/Basic/DiagnosticSemaKinds.td:7775 @@ -7772,1 +7774,3 @@ +def note_module_need_top_level : Note<"consider moving the import to top level">; +def note_module_need_textual : Note<"consider marking the header as textual">; } ---------------- rsmith wrote: > Textual headers are not the common case, so "consider" seems too strong; how > about weakening this to something like: > > "if this header is intended to be included textually, mark it 'textual' in > the module map" This message is also removed, as Sean proposed. ================ Comment at: lib/Parse/ParseDeclCXX.cpp:213 @@ -212,2 +212,3 @@ if (index == Ident.size()) { - while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + while (tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { ---------------- rsmith wrote: > Move this `try...` call to the end of the `&&` here and elsewhere; it's much > more likely that we'll hit an `r_brace`. Moved. ================ Comment at: lib/Parse/Parser.cpp:2023-2024 @@ +2022,4 @@ +/// be found. +/// \returns true if the recover was successful and parsing may be continued, or +/// false if parser must bail out to top level and handle the token there. +bool Parser::tryParseMisplacedModuleImport() { ---------------- rsmith wrote: > This is the opposite of how all the other `try` functions behave: they return > `true` if they consumed the thing they were asked to consume. Meaning of the return value is inverted. ================ Comment at: lib/Parse/Parser.cpp:2025-2027 @@ +2024,5 @@ +/// false if parser must bail out to top level and handle the token there. +bool Parser::tryParseMisplacedModuleImport() { + while (true) { + switch (Tok.getKind()) { + case tok::annot_module_end: ---------------- rsmith wrote: > Refactor this as follows: > > Rename this to `parseMisplacedModuleImport`. Add an inline > `tryParseMisplacedModuleImport` to Parser.h, which checks if the current > token is an EOM token. If it is, it calls this function. If it is not, it > returns immediately. > > The purpose of having these `try` functions with thin wrappers in the .h file > is so that we can inline the cheap "are we looking at the right kind of > token" check (and allow it to be combined with other nearby checks on the > token kind). Thank you for explanation. Fixed. ================ Comment at: lib/Sema/SemaDecl.cpp:14361-14366 @@ -14359,6 +14360,8 @@ if (!isa<TranslationUnitDecl>(DC)) { - S.Diag(ImportLoc, diag::err_module_import_not_at_top_level) - << M->getFullModuleName() << DC; - S.Diag(cast<Decl>(DC)->getLocStart(), - diag::note_module_import_not_at_top_level) - << DC; + if (DC->isNamespace()) { + S.Diag(ImportLoc, diag::err_module_import_not_at_top_level) + << M->getFullModuleName() << DC; + S.Diag(cast<Decl>(DC)->getLocStart(), + diag::note_module_import_not_at_top_level) << DC; + S.Diag(ImportLoc, diag::note_module_need_top_level); + } else { ---------------- rsmith wrote: > It looks like this will currently produce repeated diagnostics for an import > within multiple namespaces: > > module.map: > module Foo { module X { header "foo1.h" } module Y { header "foo2.h" } } > > foo1.h: > namespace A { > namespace B { > #include "foo2.h" > } > } > > I believe this will diagnose: > 1) import of "Foo.Y" within "B" > 2) expected } at end of "B" > 3) import of "Foo.Y" within "A" > 4) expected } at end of "A" > > I think we should treat this case as fatal too. Yes, the messages were as you described. Now import inside a namespace is also a fatal error. Test `misplaced-4.cpp` checks this case. ================ Comment at: lib/Sema/SemaDecl.cpp:14372 @@ +14371,3 @@ + diag::note_module_import_not_at_top_level) << DC; + S.Diag(ImportLoc, diag::note_module_need_textual); + } ---------------- silvas wrote: > rsmith wrote: > > I think we should only suggest changing the module map if our current > > module and the module of the included file are within the same top-level > > module. It would be unfortunate for us to suggest modifying, say, the libc > > module map if we see some end user's code including a C library header in > > the wrong context. > > > > You can check `M->getTopLevelModuleName()` against > > `S.getLangOpts().CurrentModule` and > > `S.getLangOpts().ImplementationOfModule` to see whether it's a submodule of > > the current module. > From my experience, your suggested heuristic is insufficient; we definitely > need to cover the case that crosses top-level modules (or is from a .cpp file > to a module it imports); actually, that is the only case that I have run into > in practice. > > In this patch, I think the right thing is to just not emit > `note_module_need_top_level` nor `note_module_need_textual`. A separate patch > can use a flag `-Wintial-modules-migration` (or whatever) to emit these notes > a bit more aggressively (the flag would be off by default). As Sean proposed, these are not emitted. ================ Comment at: test/Modules/misplaced.cpp:1-12 @@ +1,12 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -verify + +namespace N1 { // expected-note{{namespace 'N1' begins here}} +#include "dummy.h" // expected-error{{import of module 'dummy' appears within namespace 'N1'}} \ + // expected-note{{consider moving the import to top level}} +} + +void func1() { // expected-note{{function 'func1' begins here}} +#include "dummy.h" // expected-error{{import of module 'dummy' appears within function 'func1'}} \ + // expected-note{{consider marking the header as textual}} +} ---------------- silvas wrote: > This test does not cover the `appears within class` case. This case was checked in `malformed.cpp` but for the sake of consistency separate test was added. http://reviews.llvm.org/D11844 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits