On Nov 10, 2010, at 9:34 PM, Argyrios Kyrtzidis wrote:

> Diagnostic pragmas are broken because we don't keep track of the diagnostic 
> state changes and we only check the current/latest state.
> Problems manifest if a diagnostic is emitted for a source line that has 
> different diagnostic state than the current state; this can affect
> a lot of places, like C++ inline methods, template instantiations, the lexer, 
> etc. For example:
> 
> struct S {
> #pragma clang diagnostic push
> #pragma clang diagnostic ignored "-Wtautological-compare"
>       void m() { int b = b==b; }
> #pragma clang diagnostic pop
> };
> 
> the pragmas do not work for suppressing the warning in the above case.
> 
> The attached patch fixes the issue by having the Diagnostic object keep track 
> of the source location of the pragmas so that it is able to know what is the 
> diagnostic state at any given source location.

This is really cool, Argiris!

@@ -365,33 +376,56 @@ void Diagnostic::ReportDelayed() {
   DelayedDiagArg2.clear();
 }
 
+Diagnostic::DiagStatePointsTy::iterator
+Diagnostic::GetDiagStatePointForLoc(FullSourceLoc Loc) const {
+  assert(!DiagStatePoints.empty());
+  assert(DiagStatePoints.front().Loc.isInvalid() &&
+         "Should have created a DiagStatePoint for command-line");
+
+  if (Loc.isInvalid())
+    return DiagStatePoints.begin();

I guess I was expecting that we would return the last DiagStatePoint for an 
invalid location (so that we get the most recent state), rather than the first.

diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index 4a40405..51b6dae 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -252,12 +252,14 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool 
isEndOfMacro) {
 
   // This is the end of the top-level file.  If the diag::pp_macro_not_used
   // diagnostic is enabled, look for macros that have not been used.
-  if (getDiagnostics().getDiagnosticLevel(diag::pp_macro_not_used) !=
-        Diagnostic::Ignored) {
-    for (macro_iterator I = macro_begin(false), E = macro_end(false); 
-         I != E; ++I)
-      if (!I->second->isUsed())
-        Diag(I->second->getDefinitionLoc(), diag::pp_macro_not_used);
+  for (macro_iterator I = macro_begin(false), E = macro_end(false); 
+       I != E; ++I) {
+    if (I->second->isUsed())
+      continue;
+    FullSourceLoc DefLoc(I->second->getDefinitionLoc(), getSourceManager());
+    if (getDiagnostics().getDiagnosticLevel(diag::pp_macro_not_used, DefLoc) !=
+        Diagnostic::Ignored)
+      Diag(DefLoc, diag::pp_macro_not_used);
   }

It's unfortunate this fixing this check means that we always have to iterate 
over all of the macros. In particular, I wonder if this causes deserialization 
of macros of a PCH file, which would be a performance killer. Could you check?

> I've also made measurements to see how this fix impacts performance. I 
> basically measured how long it takes to do a -fsyntax-only over the 
> llvm/clang codebase and the results were:
> 
> before the fix: 722.83 sec
> after the fix: 727.24 sec
> 
> So avoiding the fix only provides a 0.6% gain.


Other than the above, I didn't notice any other opportunities for optimization 
here. I think we have to suck up the cost in the name of correctness.

        - Doug
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to