VerifyDiagnosticConsumer and ModuleMapParser
Ben Langmuir
blangmuir at apple.com
Thu Nov 6 09:45:03 PST 2014
> On Nov 3, 2014, at 2:38 PM, Vassil Vassilev <vvasilev at cern.ch> wrote:
>
> On 03/11/14 16:49, Ben Langmuir wrote:
>>> On Nov 3, 2014, at 2:10 AM, Vassil Vassilev <vvasilev at cern.ch> wrote:
>>>
>>> Hi guys,
>>> I am working on http://llvm.org/bugs/show_bug.cgi?id=20507 Now the diagnostic gets issued for:
>>> Clang :: Modules/declare-use1.cpp
>>> Clang :: Modules/declare-use2.cpp
>>> Clang :: Modules/declare-use3.cpp
>>> Clang :: Modules/strict-decluse.cpp
>>>
>>> It says smth like: Modules/Inputs/declare-use/module.map:30:10: note: Header file 'unavailable.h' not present in module 'XF'
>>>
>>> I'd like to add an expected diag to the modulemap file. Eg:
>>> module XF {
>>> ...
>>> header "unavailable.h" // expected-note {{...}}
>>> ...
>>> }
>>>
>>> Is that the right way to go?
>>>
>>> If yes, VerifyDiagnosticConsumer requires some callbacks (such as HandleComment) which come from the Preprocessor. In the ModuleMapParser we use raw lexing (without PP at all) and I was wondering what would be the right way to go, in order to make the -verify flag work inside the module maps. One solution that I see is to pass the comment handlers from the PP to the ModuleMapParser, however IMO this would break the encapsulation. Do you have better ideas?
>> Rather than complicate the module map parsing, we could always put the // expected line into the importing source file (using @file:line). I thought this would Just Work (TM), but when I tried some silly examples the verification didn’t work. I don’t know if that’s related to it being a module map file or something to do with the fatal error. I’m not sure what’s going wrong there, but that’s the direction I would explore.
> Thanks for the pointers. I have prepared a starter already. Wording of the diagnostic probably needs rewording :) Do you mind having a look? Thanks!
Sorry for the delay! Some comments:
> Index: include/clang/Basic/DiagnosticCommonKinds.td
> ===================================================================
> --- include/clang/Basic/DiagnosticCommonKinds.td (revision 220824)
> +++ include/clang/Basic/DiagnosticCommonKinds.td (working copy)
> @@ -141,6 +141,7 @@
>
> // Modules
> def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'”>;
> +def note_module_header_missing : Note<"Header file '%0' not present in module '%1'”>;
We don’t capitalize the start of diagnostic messages. I suggest something like:
“header ‘%0’ required by module ‘%1’ not found”
or even
“header ‘%0’ not found"
>
> // TransformActions
> // TODO: Use a custom category name to distinguish rewriter errors.
> Index: lib/Lex/ModuleMap.cpp
> ===================================================================
> --- lib/Lex/ModuleMap.cpp (revision 220824)
> +++ lib/Lex/ModuleMap.cpp (working copy)
> @@ -311,6 +311,15 @@
> }
> }
>
> +void ModuleMap::diagnoseModuleMissingRequirements(Module *M) {
> + assert(M && "Must not be null");
> + for(auto& Header: M->MissingHeaders) {
> + Diags.Report(Header.FileNameLoc, diag::note_module_header_missing)
> + << Header.FileName
> + << M->getFullModuleName();
> + }
> +}
This is using notes, but they need to be attached to an error (maybe you just haven’t added this yet?). I would have something like:
#include “foo.h” // error: could not import module ‘Foo’
// @ Foo’s module map: note: header ‘bar.h’ required by module ‘Foo’ not found
// @ Foo’s module map: note: header ‘baz.h’ required by module ‘Foo’ not found
As you have already discovered in your test cases below, this is going to overlap with the “-fmodule-strict-decluse” and “-Wnon-modular-include” diagnostics when we fall back to the textual include. We need to suppress those diagnostics when we diagnose a failed import like this, or we need to make the failed import a fatal error. I would probably go with the former option, what do you think?
> +
> ModuleMap::KnownHeader
> ModuleMap::findModuleForHeader(const FileEntry *File,
> Module *RequestingModule,
> @@ -331,8 +340,11 @@
> E = Known->second.end();
> I != E; ++I) {
> // Cannot use a module if it is unavailable.
> - if (!I->getModule()->isAvailable())
> + if (!I->getModule()->isAvailable()) {
> + //TODO: Propagate the Loc of the requesting header.
> + diagnoseModuleMissingRequirements(I->getModule()/*, IncludeLoc*/);
> continue;
> + }
>
> // If 'File' is part of 'RequestingModule', 'RequestingModule' is the
> // module we are looking for.
> Index: test/Modules/declare-use2.cpp
> ===================================================================
> --- test/Modules/declare-use2.cpp (revision 220824)
> +++ test/Modules/declare-use2.cpp (working copy)
> @@ -3,5 +3,5 @@
>
> #include "h.h"
> #include "e.h"
> -#include "f.h" // expected-error {{module XH does not depend on a module exporting 'f.h'}}
> +#include "f.h" // expected-error {{module XH does not depend on a module exporting 'f.h'}} // expected-note at module.map:30 {{Header file 'unavailable.h' not present in module 'XF'}}
> const int h2 = h1+e+f;
> Index: test/Modules/Inputs/declare-use/f.h
> ===================================================================
> --- test/Modules/Inputs/declare-use/f.h (revision 220824)
> +++ test/Modules/Inputs/declare-use/f.h (working copy)
> @@ -1,6 +1,6 @@
> #ifndef F_H
> #define F_H
> -#include "a.h"
> -#include "b.h"
> +#include "a.h" // expected-note at module.map:30 {{Header file 'unavailable.h' not present in module 'XF'}}
> +#include "b.h" // expected-note at module.map:30 {{Header file 'unavailable.h' not present in module 'XF'}}
> const int f = a+b;
> #endif
> Index: test/Modules/Inputs/declare-use/h.h
> ===================================================================
> --- test/Modules/Inputs/declare-use/h.h (revision 220824)
> +++ test/Modules/Inputs/declare-use/h.h (working copy)
> @@ -1,7 +1,7 @@
> #ifndef H_H
> #define H_H
> -#include "c.h"
> -#include "d.h" // expected-error {{does not depend on a module exporting}}
> -#include "h1.h"
> +#include "c.h" // expected-note at module.map:23 {{Header file 'unavailable.h' not present in module 'XE'}}
> +#include "d.h" // expected-error {{does not depend on a module exporting}} // expected-note at module.map:23 {{Header file 'unavailable.h' not present in module 'XE'}}
> +#include "h1.h" // expected-note at module.map:23 {{Header file 'unavailable.h' not present in module 'XE'}}
> const int h1 = aux_h*c*7*d;
> #endif
> Index: include/clang/Lex/ModuleMap.h
> ===================================================================
> --- include/clang/Lex/ModuleMap.h (revision 220824)
> +++ include/clang/Lex/ModuleMap.h (working copy)
> @@ -274,6 +274,10 @@
> void diagnoseHeaderInclusion(Module *RequestingModule,
> SourceLocation FilenameLoc, StringRef Filename,
> const FileEntry *File);
> + /// \brief Reports issues when a module declaration doesn't match the
> + /// requirements and will be marked as not available.
> + ///
> + void diagnoseModuleMissingRequirements(Module *M);
>
> /// \brief Determine whether the given header is part of a module
> /// marked 'unavailable'.
>
> Vassil
>>
>> Ben
>>
>>> Many thanks,
>>> Vassil
>
>
> --
> --------------------------------------------
> Q: Why is this email five sentences or less?
> A: http://five.sentenc.es
>
> <bug20507.diff>
More information about the cfe-commits
mailing list