aaron.ballman added inline comments.

================
Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:161
+
+  const SmallVector<StringRef, 1>& getCheckNames() const {
+    assert(isNolintFound());
----------------
aaron.ballman wrote:
> The `&` should bind to the right. However, instead of returning the concrete 
> container, why not expose a range interface instead?
This could use a typedef to make the return type more readable. Also, the 
function should be `checkName()`, dropping the "get".


================
Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:276
+
+  using NolintMap = std::unordered_map<NolintTargetInfo,
+                                       NolintCommentInfo,
----------------
xgsa wrote:
> aaron.ballman wrote:
> > Is there a better LLVM ADT to use here?
> This data structure provides the fast lookup by check name+line number and 
> it's exactly what is necessary. What are the concerns about this data 
> structure?
Same as above.


================
Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:381
 
+void ClangTidyContext::setPreprocessor(Preprocessor *preprocessor) {
+  if (preprocessor && isCheckEnabled(NolintCheckName)) {
----------------
aaron.ballman wrote:
> Name does not match coding standard.
Please do not name the parameter the same as a type name.


================
Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:424
+// This method is not const, because it fills cache on first demand.
+// It is possible to fill cache in constructor or make cache volatile
+// and make this method const, but they seem like worse solutions.
----------------
xgsa wrote:
> aaron.ballman wrote:
> > Making the cache volatile will have no impact on this.
> > 
> > Any reason not to make the cache `mutable`, however? That's quite common 
> > for implementation details.
> Sorry, certainly, instead of "volatile" I meant "mutable".
> 
> Actually, using of "mutable" violates a constancy contract, as the field is 
> get modified in a const method. Thus I'd tend to avoid using `mutable`, if 
> possible, because e.g. in multi-threaded applications these fields require 
> additional protection/synchronization. Moreover, I see that using of  
> `mutable` is not very spread in clang-tidy. Thus as, currently, `hasCheck` is 
> called from the non-constant context, I'd prefer leaving it non-const instead 
> of making cache `mutable`. Please, let me know if you insist on the `mutable` 
> option.
Use of mutable does not violate constancy; the cache is not exposed via any 
interface; it is purely an implementation detail. Very little of our code base 
is concerned with multithreaded scenarios (we use bit-fields *everywhere*, for 
instance).

I won't insist on using `mutable` if you are set against it, but this is the 
exact scenario in which it is the correct solution.


================
Comment at: clang-tidy/ClangTidyDiagnosticConsumer.cpp:839-840
+        case NolintCommentType::Nolint:
+          Message = "there is no diagnostics on this line, "
+                    "the NOLINT comment is redundant";
+          break;
----------------
xgsa wrote:
> aaron.ballman wrote:
> > I don't think the user is going to care about the distinction between no 
> > diagnostics being triggered and the expected diagnostic not being 
> > triggered. Also, it's dangerous to claim the lint comment is redundant 
> > because it's possible the user has NOLINT(foo, bar) and while foo is not 
> > triggered, bar still is. The NOLINT comment itself isn't redundant, it's 
> > that the check specified doesn't occur.
> > 
> > I would consolidate those scenarios into a single diagnostic: "expected 
> > diagnostic '%0' not generated" and "expected diagnostic '%0' not generated 
> > for the following line".
> > 
> > One concern I have with this functionality is: how should users silence a 
> > lint diagnostic that's target sensitive? e.g., a diagnostic that triggers 
> > based on the underlying type of size_t or the signedness of plain char. In 
> > that case, the diagnostic may trigger for some targets but not others, but 
> > on the targets where the diagnostic is not triggered, they now get a 
> > diagnostic they cannot silence. There should be a way to silence the "bad 
> > NOLINT" diagnostics.
> > I don't think the user is going to care about the distinction between no 
> > diagnostics being triggered and the expected diagnostic not being 
> > triggered. Also, it's dangerous to claim the lint comment is redundant 
> > because it's possible the user has NOLINT(foo, bar) and while foo is not 
> > triggered, bar still is. The NOLINT comment itself isn't redundant, it's 
> > that the check specified doesn't occur.
> > 
> > I would consolidate those scenarios into a single diagnostic: "expected 
> > diagnostic '%0' not generated" and "expected diagnostic '%0' not generated 
> > for the following line".
> 
> This branch of `if (NolintEntry.first.CheckName == 
> NolintCommentsCollector::AnyCheck)` reports only about 
> `NOLINT`/`NOLINTNEXTLINE` comments without check list, so I suppose it's fair 
> to claim that this comment is redundant (we have already checked that no 
> single check reported diagnostics on the line). The `else`-branch reports the 
> diagnostics for the definite check in a list in case of `NOLINT(foo, bar)` 
> (actually, if neither `foo` nor `bar` checks reported diagnostics for the 
> line, there will be a few diagnostics from `nolint-usage` - not sure if it's 
> good, but it seems acceptable). That is why, I suppose, it is necessary to 
> distinct these cases.
> 
> > One concern I have with this functionality is: how should users silence a 
> > lint diagnostic that's target sensitive? e.g., a diagnostic that triggers 
> > based on the underlying type of size_t or the signedness of plain char. In 
> > that case, the diagnostic may trigger for some targets but not others, but 
> > on the targets where the diagnostic is not triggered, they now get a 
> > diagnostic they cannot silence. There should be a way to silence the "bad 
> > NOLINT" diagnostics.
> 
> There is such mechanism: it is possible to specify `// NOLINT(nolint-usage)` 
> or `//NOLINT(check1, check2, nolint-usage) to silence the 
> `nolint-usage`-mechanism. Please, see tests for details and more examples. 
Can you provide an example where this distinction will make a difference to the 
user and help clarify a confusing situation? I cannot think of one, and it 
would be nice to simplify this code.

Thank you for the explanation about nolint-usage. This is not terminology I've 
seen before -- is this your invention, or is it a documented feature for NOLINT 
comments?


================
Comment at: clang-tidy/ClangTidyDiagnosticConsumer.h:295
+  // separately to process NOLINT misuse.
+  std::unordered_map<unsigned, std::vector<unsigned>> DiagIDsToLineNumbers;
 };
----------------
xgsa wrote:
> aaron.ballman wrote:
> > Perhaps this would make more sense as an `llvm::IndexedMap` or other 
> > non-STL datatype?
> I think, the map of vectors fits well: it provides efficient adding, storing 
> and iterating through elements. In spite items in vector can be duplicated, 
> it's not a usual case (when there are a lot of diagnostics for the same check 
> on the same line), so I don't think it worth using set. I don't see how 
> `llvm::IndexedMap` could help here. What are the concerns about the current 
> data structure?
STL data structures are not particularly well-optimized; they're meant for 
general usage cases. This map can get very large in real projects, so I worry 
about performance concerns. That's why we have specialized ADTs -- you should 
generally prefer them to STL containers.


https://reviews.llvm.org/D41326



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to