Index: include/clang/Lex/Lexer.h
===================================================================
--- include/clang/Lex/Lexer.h	(revision 58184)
+++ include/clang/Lex/Lexer.h	(working copy)
@@ -71,10 +71,12 @@
   /// whitespace preservation can be useful for some clients that want to lex
   /// the file in raw mode and get every character from the file.
   ///
-  /// When this is set to 2 it returns comments and whitespace.  When set to 1
-  /// it returns comments, when it is set to 0 it returns normal tokens only.
+  /// When this is set to 3 it returns comments and whitespace. When set to 2
+  /// it returns comments. When set to 1 it call the PP callback on comment but
+  /// only return normal tokens. When it is set to 0 it returns normal tokens
+  /// only.
   unsigned char ExtendedTokenMode;
-  
+
   //===--------------------------------------------------------------------===//
   // Context that changes as the file is lexed.
   // NOTE: any state that mutates when in raw mode must have save/restore code
@@ -161,7 +163,7 @@
   /// should only be used in raw mode, as the preprocessor is not prepared to
   /// deal with the excess tokens.
   bool isKeepWhitespaceMode() const {
-    return ExtendedTokenMode > 1;
+    return ExtendedTokenMode > 2;
   }
 
   /// SetKeepWhitespaceMode - This method lets clients enable or disable
@@ -169,13 +171,13 @@
   void SetKeepWhitespaceMode(bool Val) {
     assert((!Val || LexingRawMode) &&
            "Can only enable whitespace retention in raw mode");
-    ExtendedTokenMode = Val ? 2 : 0;
+    ExtendedTokenMode = Val ? 3 : 0;
   }
 
   /// inKeepCommentMode - Return true if the lexer should return comments as
   /// tokens.
   bool inKeepCommentMode() const {
-    return ExtendedTokenMode > 0;
+    return ExtendedTokenMode > 1;
   }
   
   /// SetCommentRetentionMode - Change the comment retention mode of the lexer
@@ -184,10 +186,28 @@
   void SetCommentRetentionState(bool Mode) { 
     assert(!isKeepWhitespaceMode() &&
            "Can't play with comment retention state when retaining whitespace");
+    ExtendedTokenMode = Mode ? 2 : 0;
+  }
+
+  /// inLexCommentMode - Return true if the lexer should process comments as
+  /// tokens.
+  bool inLexCommentMode() const {
+    return ExtendedTokenMode > 0;
+  }
+  /// isCommentCallbackMode - Return true if the lexer should call the callback
+  /// on comments.
+  bool isCommentCallbackMode() const {
+    return ExtendedTokenMode == 1;
+  }
+
+  /// SetCommentCallbackState - Change the comment callback mode of the lexer
+  /// to the specified mode.
+  void SetCommentCallbackState(bool Mode) { 
+    assert(!inKeepCommentMode() &&
+           "Can't play with comment callback state when retaining comment");
     ExtendedTokenMode = Mode ? 1 : 0;
   }
   
-  
   /// ReadToEndOfLine - Read the rest of the current preprocessor line as an
   /// uninterpreted string.  This switches the lexer out of directive mode.
   std::string ReadToEndOfLine();
Index: include/clang/Lex/PPCallbacks.h
===================================================================
--- include/clang/Lex/PPCallbacks.h	(revision 58184)
+++ include/clang/Lex/PPCallbacks.h	(working copy)
@@ -46,6 +46,11 @@
   virtual void Ident(SourceLocation Loc, const std::string &str) {
   }
   
+  /// Comment - This callback is invoked when a comment is encountered
+  /// only when ...
+  virtual void Comment(SourceLocation Loc, unsigned Length) {
+  }
+
 };
 
 }  // end namespace clang
Index: include/clang/Lex/Preprocessor.h
===================================================================
--- include/clang/Lex/Preprocessor.h	(revision 58184)
+++ include/clang/Lex/Preprocessor.h	(working copy)
@@ -66,6 +66,7 @@
   // State that is set before the preprocessor begins.
   bool KeepComments : 1;
   bool KeepMacroComments : 1;
+  bool CallbackOnComment : 1;
   
   // State that changes while the preprocessor runs:
   bool DisableMacroExpansion : 1;  // True if macro expansion is disabled.
@@ -187,6 +188,9 @@
   }
   
   bool getCommentRetentionState() const { return KeepComments; }
+
+  void SetCommentCallbackState(bool state) { CallbackOnComment = state; }
+  bool getCommentCallbackState() const { return CallbackOnComment; }
   
   /// isCurrentLexer - Return true if we are lexing directly from the specified
   /// lexer.
Index: lib/Lex/Lexer.cpp
===================================================================
--- lib/Lex/Lexer.cpp	(revision 58184)
+++ lib/Lex/Lexer.cpp	(working copy)
@@ -102,6 +102,7 @@
   // Default to keeping comments if the preprocessor wants them.
   ExtendedTokenMode = 0;
   SetCommentRetentionState(PP->getCommentRetentionState());
+  SetCommentCallbackState(PP->getCommentCallbackState());
 }
 
 /// Lexer constructor - Create a new raw lexer object.  This object is only
@@ -804,8 +805,13 @@
   // Found but did not consume the newline.
     
   // If we are returning comments as tokens, return this comment as a token.
-  if (inKeepCommentMode())
-    return SaveBCPLComment(Result, CurPtr);
+  if (inLexCommentMode()) {
+    // This always return true.
+    SaveBCPLComment(Result, CurPtr);
+    if (inKeepCommentMode()) return true;
+    // We are in CallbackComment mode here
+    PP->getPPCallbacks()->Comment(Result.getLocation(), Result.getLength());
+  }
 
   // If we are inside a preprocessor directive and we see the end of line,
   // return immediately, so that the lexer can return this as an EOM token.
@@ -1041,7 +1047,9 @@
   }
   
   // If we are returning comments as tokens, return this comment as a token.
-  if (inKeepCommentMode()) {
+  if(isCommentCallbackMode()) {
+    PP->getPPCallbacks()->Comment(getSourceLocation(BufferPtr), CurPtr-BufferPtr);
+  } else if (inKeepCommentMode()) {
     FormTokenWithChars(Result, CurPtr, tok::comment);
     return true;
   }
@@ -1303,10 +1311,10 @@
     
     // If the next token is obviously a // or /* */ comment, skip it efficiently
     // too (without going through the big switch stmt).
-    if (CurPtr[0] == '/' && CurPtr[1] == '/' && !inKeepCommentMode()) {
+    if (CurPtr[0] == '/' && CurPtr[1] == '/' && !inLexCommentMode()) {
       SkipBCPLComment(Result, CurPtr+2);
       goto SkipIgnoredUnits;
-    } else if (CurPtr[0] == '/' && CurPtr[1] == '*' && !inKeepCommentMode()) {
+    } else if (CurPtr[0] == '/' && CurPtr[1] == '*' && !inLexCommentMode()) {
       SkipBlockComment(Result, CurPtr+2);
       goto SkipIgnoredUnits;
     } else if (isHorizontalWhitespace(*CurPtr)) {
