Re: r293123 - Remove and replace DiagStatePoint tracking and lookup data structure.
On 28 Jan 2017 8:16 pm, "Duncan P. N. Exon Smith via cfe-commits" < cfe-commits@lists.llvm.org> wrote: Hi Richard, This commit makes one of the tests fail in: https://reviews.llvm.org/D27689 The implicit modules model expects to be able to "upgrade" an implicit PCM with more -Werror flags *without* affecting the signature. However, with your commit, the command-line diagnostic flags (e.g., -Wconversion vs -Wno-conversion) now change the AST, and thus change the ASTFileSignature. One possible hammer would be to disable this pragma-diagnostic-stuff somehow for implicit modules. Do you have any other suggestions? I think that upgrade model is incorrect in the fully general case. For instance, in C++, enabling more warning flags in the definition of a template can cause behaviour changes in users of the template. Likewise, in C, as I recall we'll sometimes look at the warning state at the point of definition of a macro to determine whether to emit a warning in a macro expansion. That said, for implicit modules we can probably assume that the effects of changing the starting state can be simulated. Right now ,the implicit / explicit module decision is not made until the point of import, so we would need to commit to that earlier to avoid emitting the information at all in that case. Another alternative would be to exclude the diagnostic settings in the initial state from the hash, either by never emitting it and recomputing it from the diagnostic flags as needed, or by emitting it into an unhashed portion of the file. Thanks, Duncan > On 2017-Jan-25, at 17:01, Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > > Author: rsmith > Date: Wed Jan 25 19:01:01 2017 > New Revision: 293123 > > URL: http://llvm.org/viewvc/llvm-project?rev=293123=rev > Log: > Remove and replace DiagStatePoint tracking and lookup data structure. > > Rather than storing a single flat list of SourceLocations where the diagnostic > state changes (in source order), we now store a separate list for each FileID > in which there is a diagnostic state transition. (State for other files is > built and cached lazily, on demand.) This has two consequences: > > 1) We can now sensibly support modules, and properly track the diagnostic state > for modular headers (this matters when, for instance, triggering instantiation > of a template defined within a module triggers diagnostics). > > 2) It's much faster than the old approach, since we can now just do a binary > search on the offsets within the FileID rather than needing to call > isBeforeInTranslationUnit to determine source order (which is surprisingly > slow). For some pathological (but real world) files, this reduces total > compilation time by more than 10%. > > For now, the diagnostic state points for modules are loaded eagerly. It seems > feasible to defer this until diagnostic state information for one of the > module's files is needed, but that's not part of this patch. > > Added: >cfe/trunk/test/Modules/diag-pragma.cpp > Modified: >cfe/trunk/include/clang/Basic/Diagnostic.h >cfe/trunk/lib/Basic/Diagnostic.cpp >cfe/trunk/lib/Basic/DiagnosticIDs.cpp >cfe/trunk/lib/Serialization/ASTReader.cpp >cfe/trunk/lib/Serialization/ASTWriter.cpp >cfe/trunk/test/Modules/Inputs/diag_pragma.h > > Modified: cfe/trunk/include/clang/Basic/Diagnostic.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ clang/Basic/Diagnostic.h?rev=293123=293122=293123=diff > == > --- cfe/trunk/include/clang/Basic/Diagnostic.h (original) > +++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Jan 25 19:01:01 2017 > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -232,40 +233,97 @@ private: > /// \brief Keeps and automatically disposes all DiagStates that we create. > std::list DiagStates; > > - /// \brief Represents a point in source where the diagnostic state was > - /// modified because of a pragma. > - /// > - /// 'Loc' can be null if the point represents the diagnostic state > - /// modifications done through the command-line. > - struct DiagStatePoint { > -DiagState *State; > -SourceLocation Loc; > -DiagStatePoint(DiagState *State, SourceLocation Loc) > - : State(State), Loc(Loc) { } > + /// A mapping from files to the diagnostic states for those files. Lazily > + /// built on demand for files in which the diagnostic state has not changed. > + class DiagStateMap { > + public: > +/// Add an initial diagnostic state. > +void appendFirst(DiagState *State); > +/// Add a new latest state point. > +void append(SourceManager , SourceLocation Loc, DiagState *State); > +/// Look up the diagnostic state at a given source location. > +DiagState *lookup(SourceManager , SourceLocation Loc) const; > +/// Determine whether this map is empty. > +bool empty() const { return
Re: r293123 - Remove and replace DiagStatePoint tracking and lookup data structure.
Hi Richard, This commit makes one of the tests fail in: https://reviews.llvm.org/D27689 The implicit modules model expects to be able to "upgrade" an implicit PCM with more -Werror flags *without* affecting the signature. However, with your commit, the command-line diagnostic flags (e.g., -Wconversion vs -Wno-conversion) now change the AST, and thus change the ASTFileSignature. One possible hammer would be to disable this pragma-diagnostic-stuff somehow for implicit modules. Do you have any other suggestions? Thanks, Duncan > On 2017-Jan-25, at 17:01, Richard Smith via cfe-commits >wrote: > > Author: rsmith > Date: Wed Jan 25 19:01:01 2017 > New Revision: 293123 > > URL: http://llvm.org/viewvc/llvm-project?rev=293123=rev > Log: > Remove and replace DiagStatePoint tracking and lookup data structure. > > Rather than storing a single flat list of SourceLocations where the diagnostic > state changes (in source order), we now store a separate list for each FileID > in which there is a diagnostic state transition. (State for other files is > built and cached lazily, on demand.) This has two consequences: > > 1) We can now sensibly support modules, and properly track the diagnostic > state > for modular headers (this matters when, for instance, triggering instantiation > of a template defined within a module triggers diagnostics). > > 2) It's much faster than the old approach, since we can now just do a binary > search on the offsets within the FileID rather than needing to call > isBeforeInTranslationUnit to determine source order (which is surprisingly > slow). For some pathological (but real world) files, this reduces total > compilation time by more than 10%. > > For now, the diagnostic state points for modules are loaded eagerly. It seems > feasible to defer this until diagnostic state information for one of the > module's files is needed, but that's not part of this patch. > > Added: >cfe/trunk/test/Modules/diag-pragma.cpp > Modified: >cfe/trunk/include/clang/Basic/Diagnostic.h >cfe/trunk/lib/Basic/Diagnostic.cpp >cfe/trunk/lib/Basic/DiagnosticIDs.cpp >cfe/trunk/lib/Serialization/ASTReader.cpp >cfe/trunk/lib/Serialization/ASTWriter.cpp >cfe/trunk/test/Modules/Inputs/diag_pragma.h > > Modified: cfe/trunk/include/clang/Basic/Diagnostic.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=293123=293122=293123=diff > == > --- cfe/trunk/include/clang/Basic/Diagnostic.h (original) > +++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Jan 25 19:01:01 2017 > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -232,40 +233,97 @@ private: > /// \brief Keeps and automatically disposes all DiagStates that we create. > std::list DiagStates; > > - /// \brief Represents a point in source where the diagnostic state was > - /// modified because of a pragma. > - /// > - /// 'Loc' can be null if the point represents the diagnostic state > - /// modifications done through the command-line. > - struct DiagStatePoint { > -DiagState *State; > -SourceLocation Loc; > -DiagStatePoint(DiagState *State, SourceLocation Loc) > - : State(State), Loc(Loc) { } > + /// A mapping from files to the diagnostic states for those files. Lazily > + /// built on demand for files in which the diagnostic state has not > changed. > + class DiagStateMap { > + public: > +/// Add an initial diagnostic state. > +void appendFirst(DiagState *State); > +/// Add a new latest state point. > +void append(SourceManager , SourceLocation Loc, DiagState *State); > +/// Look up the diagnostic state at a given source location. > +DiagState *lookup(SourceManager , SourceLocation Loc) const; > +/// Determine whether this map is empty. > +bool empty() const { return Files.empty(); } > +/// Clear out this map. > +void clear() { > + Files.clear(); > + FirstDiagState = CurDiagState = nullptr; > + CurDiagStateLoc = SourceLocation(); > +} > + > +/// Grab the most-recently-added state point. > +DiagState *getCurDiagState() const { return CurDiagState; } > +/// Get the location at which a diagnostic state was last added. > +SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } > + > + private: > +/// \brief Represents a point in source where the diagnostic state was > +/// modified because of a pragma. > +/// > +/// 'Loc' can be null if the point represents the diagnostic state > +/// modifications done through the command-line. > +struct DiagStatePoint { > + DiagState *State; > + unsigned Offset; > + DiagStatePoint(DiagState *State, unsigned Offset) > +: State(State), Offset(Offset) { } > +}; > + > +/// Description of the diagnostic states and state
r293123 - Remove and replace DiagStatePoint tracking and lookup data structure.
Author: rsmith Date: Wed Jan 25 19:01:01 2017 New Revision: 293123 URL: http://llvm.org/viewvc/llvm-project?rev=293123=rev Log: Remove and replace DiagStatePoint tracking and lookup data structure. Rather than storing a single flat list of SourceLocations where the diagnostic state changes (in source order), we now store a separate list for each FileID in which there is a diagnostic state transition. (State for other files is built and cached lazily, on demand.) This has two consequences: 1) We can now sensibly support modules, and properly track the diagnostic state for modular headers (this matters when, for instance, triggering instantiation of a template defined within a module triggers diagnostics). 2) It's much faster than the old approach, since we can now just do a binary search on the offsets within the FileID rather than needing to call isBeforeInTranslationUnit to determine source order (which is surprisingly slow). For some pathological (but real world) files, this reduces total compilation time by more than 10%. For now, the diagnostic state points for modules are loaded eagerly. It seems feasible to defer this until diagnostic state information for one of the module's files is needed, but that's not part of this patch. Added: cfe/trunk/test/Modules/diag-pragma.cpp Modified: cfe/trunk/include/clang/Basic/Diagnostic.h cfe/trunk/lib/Basic/Diagnostic.cpp cfe/trunk/lib/Basic/DiagnosticIDs.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/test/Modules/Inputs/diag_pragma.h Modified: cfe/trunk/include/clang/Basic/Diagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=293123=293122=293123=diff == --- cfe/trunk/include/clang/Basic/Diagnostic.h (original) +++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Jan 25 19:01:01 2017 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -232,40 +233,97 @@ private: /// \brief Keeps and automatically disposes all DiagStates that we create. std::list DiagStates; - /// \brief Represents a point in source where the diagnostic state was - /// modified because of a pragma. - /// - /// 'Loc' can be null if the point represents the diagnostic state - /// modifications done through the command-line. - struct DiagStatePoint { -DiagState *State; -SourceLocation Loc; -DiagStatePoint(DiagState *State, SourceLocation Loc) - : State(State), Loc(Loc) { } + /// A mapping from files to the diagnostic states for those files. Lazily + /// built on demand for files in which the diagnostic state has not changed. + class DiagStateMap { + public: +/// Add an initial diagnostic state. +void appendFirst(DiagState *State); +/// Add a new latest state point. +void append(SourceManager , SourceLocation Loc, DiagState *State); +/// Look up the diagnostic state at a given source location. +DiagState *lookup(SourceManager , SourceLocation Loc) const; +/// Determine whether this map is empty. +bool empty() const { return Files.empty(); } +/// Clear out this map. +void clear() { + Files.clear(); + FirstDiagState = CurDiagState = nullptr; + CurDiagStateLoc = SourceLocation(); +} + +/// Grab the most-recently-added state point. +DiagState *getCurDiagState() const { return CurDiagState; } +/// Get the location at which a diagnostic state was last added. +SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } + + private: +/// \brief Represents a point in source where the diagnostic state was +/// modified because of a pragma. +/// +/// 'Loc' can be null if the point represents the diagnostic state +/// modifications done through the command-line. +struct DiagStatePoint { + DiagState *State; + unsigned Offset; + DiagStatePoint(DiagState *State, unsigned Offset) +: State(State), Offset(Offset) { } +}; + +/// Description of the diagnostic states and state transitions for a +/// particular FileID. +struct File { + /// The diagnostic state for the parent file. This is strictly redundant, + /// as looking up the DecomposedIncludedLoc for the FileID in the Files + /// map would give us this, but we cache it here for performance. + File *Parent = nullptr; + /// The offset of this file within its parent. + unsigned ParentOffset = 0; + /// Whether this file has any local (not imported from an AST file) + /// diagnostic state transitions. + bool HasLocalTransitions = false; + /// The points within the file where the state changes. There will always + /// be at least one of these (the state on entry to the file). + llvm::SmallVectorStateTransitions; + + DiagState *lookup(unsigned Offset)