[cfe-commits] r158771 - in /cfe/trunk: include/clang-c/ include/clang/AST/ include/clang/Basic/ include/clang/Comments/ include/clang/Lex/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/ lib/ARCMigrate/ lib/AST/ lib/Comments/ lib/Lex/ lib/Parse/ lib/Sema/ lib/Serialization/ test/Index/ tools/arcmt-test/ tools/c-index-test/ tools/clang-check/ tools/diagtool/ tools/driver/ tools/libclang/ unittests/Frontend/ unittests/Tooling/

Dmitri Gribenko gribozavr at gmail.com
Tue Jun 19 17:34:59 PDT 2012


Author: gribozavr
Date: Tue Jun 19 19:34:58 2012
New Revision: 158771

URL: http://llvm.org/viewvc/llvm-project?rev=158771&view=rev
Log:
Structured comment parsing, first step.

* Retain comments in the AST
* Serialize/deserialize comments
* Find comments attached to a certain Decl
* Expose raw comment text and SourceRange via libclang

Added:
    cfe/trunk/include/clang/Comments/
    cfe/trunk/include/clang/Comments/RawCommentList.h
    cfe/trunk/lib/Comments/
    cfe/trunk/lib/Comments/CMakeLists.txt
    cfe/trunk/lib/Comments/Makefile
    cfe/trunk/lib/Comments/RawCommentList.cpp
    cfe/trunk/test/Index/annotate-comments.cpp
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/ExternalASTSource.h
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CMakeLists.txt
    cfe/trunk/lib/Lex/Preprocessor.cpp
    cfe/trunk/lib/Makefile
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/tools/arcmt-test/CMakeLists.txt
    cfe/trunk/tools/arcmt-test/Makefile
    cfe/trunk/tools/c-index-test/Makefile
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/clang-check/CMakeLists.txt
    cfe/trunk/tools/clang-check/Makefile
    cfe/trunk/tools/diagtool/CMakeLists.txt
    cfe/trunk/tools/diagtool/Makefile
    cfe/trunk/tools/driver/CMakeLists.txt
    cfe/trunk/tools/driver/Makefile
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CMakeLists.txt
    cfe/trunk/tools/libclang/Makefile
    cfe/trunk/tools/libclang/libclang.exports
    cfe/trunk/unittests/Frontend/Makefile
    cfe/trunk/unittests/Tooling/Makefile

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue Jun 19 19:34:58 2012
@@ -3188,6 +3188,19 @@
 CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
 
 /**
+ * \brief Given a cursor that represents a declaration, return the associated
+ * comment's source range.  The range may include multiple consecutive comments
+ * with whitespace in between.
+ */
+CINDEX_LINKAGE CXSourceRange clang_Cursor_getCommentRange(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a declaration, return the associated
+ * comment text, including comment markers.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C);
+
+/**
  * @}
  */
 

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Jun 19 19:34:58 2012
@@ -27,6 +27,7 @@
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/CanonicalType.h"
+#include "clang/Comments/RawCommentList.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -51,7 +52,6 @@
   class ASTMutationListener;
   class IdentifierTable;
   class SelectorTable;
-  class SourceManager;
   class TargetInfo;
   class CXXABI;
   // Decls
@@ -418,6 +418,30 @@
     return FullSourceLoc(Loc,SourceMgr);
   }
 
+  /// \brief All comments in this translation unit.
+  RawCommentList Comments;
+
+  /// \brief True if comments are already loaded from ExternalASTSource.
+  mutable bool CommentsLoaded;
+
+  /// \brief Mapping from declarations to their comments (stored within
+  /// Comments list), once we have already looked up the comment associated
+  /// with a given declaration.
+  mutable llvm::DenseMap<const Decl *, const RawComment *> DeclComments;
+
+  /// \brief Return the Doxygen-style comment attached to a given declaration,
+  /// without looking into cache.
+  const RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
+
+public:
+  void addComment(const RawComment &RC) {
+    Comments.addComment(RC, *this);
+  }
+
+  /// \brief Return the Doxygen-style comment attached to a given declaration.
+  /// Returns NULL if no comment is attached.
+  const RawComment *getRawCommentForDecl(const Decl *D) const;
+
   /// \brief Retrieve the attributes for the given declaration.
   AttrVec& getDeclAttrs(const Decl *D);
 

Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Tue Jun 19 19:34:58 2012
@@ -179,6 +179,9 @@
   /// \c ObjCInterfaceDecl::setExternallyCompleted().
   virtual void CompleteType(ObjCInterfaceDecl *Class) { }
 
+  /// \brief Loads comment ranges.
+  virtual void ReadComments() { }
+
   /// \brief Notify ExternalASTSource that we started deserialization of
   /// a decl or type so until FinishedDeserializing is called there may be
   /// decls that are initializing. Must be paired with FinishedDeserializing.

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Tue Jun 19 19:34:58 2012
@@ -1244,19 +1244,6 @@
   /// \returns true if LHS source location comes before RHS, false otherwise.
   bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
 
-  /// \brief Comparison function class.
-  class LocBeforeThanCompare : public std::binary_function<SourceLocation,
-                                                         SourceLocation, bool> {
-    SourceManager &SM;
-
-  public:
-    explicit LocBeforeThanCompare(SourceManager &SM) : SM(SM) { }
-
-    bool operator()(SourceLocation LHS, SourceLocation RHS) const {
-      return SM.isBeforeInTranslationUnit(LHS, RHS);
-    }
-  };
-
   /// \brief Determines the order of 2 source locations in the "source location
   /// address space".
   bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
@@ -1500,6 +1487,35 @@
   friend class ASTWriter;
 };
 
+/// \brief Comparison function object.
+template<typename T>
+class BeforeThanCompare;
+
+/// \brief Compare two source locations.
+template<>
+class BeforeThanCompare<SourceLocation> {
+  SourceManager &SM;
+
+public:
+  explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+  bool operator()(SourceLocation LHS, SourceLocation RHS) const {
+    return SM.isBeforeInTranslationUnit(LHS, RHS);
+  }
+};
+
+/// \brief Compare two non-overlapping source ranges.
+template<>
+class BeforeThanCompare<SourceRange> {
+  SourceManager &SM;
+
+public:
+  explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+  bool operator()(SourceRange LHS, SourceRange RHS) {
+    return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin());
+  }
+};
 
 }  // end namespace clang
 

Added: cfe/trunk/include/clang/Comments/RawCommentList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Comments/RawCommentList.h?rev=158771&view=auto
==============================================================================
--- cfe/trunk/include/clang/Comments/RawCommentList.h (added)
+++ cfe/trunk/include/clang/Comments/RawCommentList.h Tue Jun 19 19:34:58 2012
@@ -0,0 +1,172 @@
+//===--- RawCommentList.h - Classes for processing raw comments -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_COMMENTS_RAW_COMMENT_LIST_H
+#define LLVM_CLANG_COMMENTS_RAW_COMMENT_LIST_H
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+
+class ASTContext;
+class ASTReader;
+
+class RawComment {
+public:
+  enum CommentKind {
+    CK_Invalid,      ///< Invalid comment
+    CK_OrdinaryBCPL, ///< Any normal BCPL comments
+    CK_OrdinaryC,    ///< Any normal C comment
+    CK_BCPLSlash,    ///< \code /// stuff \endcode
+    CK_BCPLExcl,     ///< \code //! stuff \endcode
+    CK_JavaDoc,      ///< \code /** stuff */ \endcode
+    CK_Qt,           ///< \code /*! stuff */ \endcode, also used by HeaderDoc
+    CK_Merged        ///< Two or more Doxygen comments merged together
+  };
+
+  RawComment() : Kind(CK_Invalid), IsAlmostTrailingComment(false) { }
+
+  RawComment(const SourceManager &SourceMgr, SourceRange SR,
+             bool Merged = false);
+
+  CommentKind getKind() const LLVM_READONLY {
+    return (CommentKind) Kind;
+  }
+
+  bool isInvalid() const LLVM_READONLY {
+    return Kind == CK_Invalid;
+  }
+
+  bool isMerged() const LLVM_READONLY {
+    return Kind == CK_Merged;
+  }
+
+  /// Returns true if it is a comment that should be put after a member:
+  /// \code ///< stuff \endcode
+  /// \code //!< stuff \endcode
+  /// \code /**< stuff */ \endcode
+  /// \code /*!< stuff */ \endcode
+  bool isTrailingComment() const LLVM_READONLY {
+    assert(isDoxygen());
+    return IsTrailingComment;
+  }
+
+  /// Returns true if it is a probable typo:
+  /// \code //< stuff \endcode
+  /// \code /*< stuff */ \endcode
+  bool isAlmostTrailingComment() const LLVM_READONLY {
+    return IsAlmostTrailingComment;
+  }
+
+  /// Returns true if this comment is not a Doxygen comment.
+  bool isOrdinary() const LLVM_READONLY {
+    return (Kind == CK_OrdinaryBCPL) || (Kind == CK_OrdinaryC);
+  }
+
+  /// Returns true if this comment any kind of a Doxygen comment.
+  bool isDoxygen() const LLVM_READONLY {
+    return !isInvalid() && !isOrdinary();
+  }
+
+  /// Returns raw comment text with comment markers.
+  StringRef getRawText(const SourceManager &SourceMgr) const {
+    if (RawTextValid)
+      return RawText;
+
+    RawText = getRawTextSlow(SourceMgr);
+    RawTextValid = true;
+    return RawText;
+  }
+
+  SourceRange getSourceRange() const LLVM_READONLY {
+    return Range;
+  }
+
+  unsigned getBeginLine(const SourceManager &SM) const;
+  unsigned getEndLine(const SourceManager &SM) const;
+
+private:
+  SourceRange Range;
+
+  mutable StringRef RawText;
+  mutable bool RawTextValid : 1; ///< True if RawText is valid
+
+  unsigned Kind : 3;
+
+  bool IsTrailingComment : 1;
+  bool IsAlmostTrailingComment : 1;
+
+  mutable bool BeginLineValid : 1; ///< True if BeginLine is valid
+  mutable bool EndLineValid : 1;   ///< True if EndLine is valid
+  mutable unsigned BeginLine;      ///< Cached line number
+  mutable unsigned EndLine;        ///< Cached line number
+
+  /// \brief Constructor for AST deserialization.
+  RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
+             bool IsAlmostTrailingComment) :
+    Range(SR), RawTextValid(false), Kind(K),
+    IsTrailingComment(IsTrailingComment),
+    IsAlmostTrailingComment(IsAlmostTrailingComment),
+    BeginLineValid(false), EndLineValid(false)
+  { }
+
+  StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
+
+  friend class ASTReader;
+};
+
+/// \brief Compare comments' source locations.
+template<>
+class BeforeThanCompare<RawComment> {
+  const SourceManager &SM;
+
+public:
+  explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
+
+  bool operator()(const RawComment &LHS, const SourceRange &RHS) {
+    return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(),
+                                        RHS.getBegin());
+  }
+};
+
+/// \brief This class represents all comments included in the translation unit,
+/// sorted in order of appearance in the translation unit.
+class RawCommentList {
+public:
+  RawCommentList(SourceManager &SourceMgr) :
+    SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { }
+
+  void addComment(const RawComment &RC, ASTContext &Context);
+
+  ArrayRef<RawComment> getComments() const {
+    return Comments;
+  }
+
+private:
+  SourceManager &SourceMgr;
+  std::vector<RawComment> Comments;
+  RawComment LastComment;
+  bool OnlyWhitespaceSeen;
+
+  void addCommentsToFront(const std::vector<RawComment> &C) {
+    size_t OldSize = Comments.size();
+    Comments.resize(C.size() + OldSize);
+    std::copy_backward(Comments.begin(), Comments.begin() + OldSize,
+                       Comments.end());
+    std::copy(C.begin(), C.end(), Comments.begin());
+  }
+
+  friend class ASTReader;
+};
+
+} // end namespace clang
+
+#endif
+

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Tue Jun 19 19:34:58 2012
@@ -510,12 +510,12 @@
   }
 
   /// \brief Add the specified comment handler to the preprocessor.
-  void AddCommentHandler(CommentHandler *Handler);
+  void addCommentHandler(CommentHandler *Handler);
 
   /// \brief Remove the specified comment handler.
   ///
   /// It is an error to remove a handler that has not been registered.
-  void RemoveCommentHandler(CommentHandler *Handler);
+  void removeCommentHandler(CommentHandler *Handler);
 
   /// \brief Set the code completion handler to the given object.
   void setCodeCompletionHandler(CodeCompletionHandler &Handler) {

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Jun 19 19:34:58 2012
@@ -170,6 +170,7 @@
   OwningPtr<PragmaHandler> RedefineExtnameHandler;
   OwningPtr<PragmaHandler> FPContractHandler;
   OwningPtr<PragmaHandler> OpenCLExtensionHandler;
+  OwningPtr<CommentHandler> CommentHandler;
 
   /// Whether the '>' token acts as an operator or not. This will be
   /// true except when we are parsing an expression within a C++

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 19 19:34:58 2012
@@ -849,6 +849,8 @@
   /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
   SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
 
+  void ActOnComment(SourceRange Comment);
+
   //===--------------------------------------------------------------------===//
   // Type Analysis / Processing: SemaType.cpp.
   //

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Jun 19 19:34:58 2012
@@ -207,7 +207,10 @@
       PREPROCESSOR_DETAIL_BLOCK_ID,
       
       /// \brief The block containing the submodule structure.
-      SUBMODULE_BLOCK_ID
+      SUBMODULE_BLOCK_ID,
+
+      /// \brief The block containing comments.
+      COMMENTS_BLOCK_ID
     };
 
     /// \brief Record types that occur within the AST block itself.
@@ -545,7 +548,12 @@
       /// \brief Specifies a required feature.
       SUBMODULE_REQUIRES = 7
     };
-    
+
+    /// \brief Record types used within a comments block.
+    enum CommentRecordTypes {
+      COMMENTS_RAW_COMMENT = 0
+    };
+
     /// \defgroup ASTAST AST file AST constants
     ///
     /// The constants in this group describe various components of the

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Jun 19 19:34:58 2012
@@ -1501,6 +1501,13 @@
   SwitchCase *getSwitchCaseWithID(unsigned ID);
 
   void ClearSwitchCaseIDs();
+
+  /// \brief Cursors for comments blocks.
+  SmallVector<std::pair<llvm::BitstreamCursor,
+                        serialization::ModuleFile *>, 8> CommentsCursors;
+
+  /// \brief Loads comments ranges.
+  void ReadComments();
 };
 
 /// \brief Helper class that saves the current stream position and

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Tue Jun 19 19:34:58 2012
@@ -414,6 +414,7 @@
   uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
   void WriteTypeDeclOffsets();
   void WriteFileDeclIDsMap();
+  void WriteComments();
   void WriteSelectors(Sema &SemaRef);
   void WriteReferencedSelectorsPool(Sema &SemaRef);
   void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,

Modified: cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp Tue Jun 19 19:34:58 2012
@@ -44,7 +44,7 @@
   SourceManager &SM = Ctx.getSourceManager();
   std::vector<SourceLocation>::iterator
     I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc,
-                         SourceManager::LocBeforeThanCompare(SM));
+                         BeforeThanCompare<SourceLocation>(SM));
   --I;
   SourceLocation
       AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jun 19 19:34:58 2012
@@ -53,6 +53,107 @@
   HalfRank, FloatRank, DoubleRank, LongDoubleRank
 };
 
+const RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
+  if (!CommentsLoaded && ExternalSource) {
+    ExternalSource->ReadComments();
+    CommentsLoaded = true;
+  }
+
+  assert(D);
+
+  // TODO: handle comments for function parameters properly.
+  if (isa<ParmVarDecl>(D))
+    return NULL;
+
+  ArrayRef<RawComment> RawComments = Comments.getComments();
+
+  // If there are no comments anywhere, we won't find anything.
+  if (RawComments.empty())
+    return NULL;
+
+  // If the declaration doesn't map directly to a location in a file, we
+  // can't find the comment.
+  SourceLocation DeclLoc = D->getLocation();
+  if (DeclLoc.isInvalid() || !DeclLoc.isFileID())
+    return NULL;
+
+  // Find the comment that occurs just after this declaration.
+  ArrayRef<RawComment>::iterator Comment
+      = std::lower_bound(RawComments.begin(),
+                         RawComments.end(),
+                         SourceRange(DeclLoc),
+                         BeforeThanCompare<RawComment>(SourceMgr));
+
+  // Decompose the location for the declaration and find the beginning of the
+  // file buffer.
+  std::pair<FileID, unsigned> DeclLocDecomp = SourceMgr.getDecomposedLoc(DeclLoc);
+
+  // First check whether we have a trailing comment.
+  if (Comment != RawComments.end() &&
+      Comment->isDoxygen() && Comment->isTrailingComment() &&
+      !isa<TagDecl>(D) && !isa<NamespaceDecl>(D)) {
+    std::pair<FileID, unsigned> CommentBeginDecomp
+      = SourceMgr.getDecomposedLoc(Comment->getSourceRange().getBegin());
+    // Check that Doxygen trailing comment comes after the declaration, starts
+    // on the same line and in the same file as the declaration.
+    if (DeclLocDecomp.first == CommentBeginDecomp.first &&
+        SourceMgr.getLineNumber(DeclLocDecomp.first, DeclLocDecomp.second)
+          == SourceMgr.getLineNumber(CommentBeginDecomp.first,
+                                     CommentBeginDecomp.second)) {
+      return &*Comment;
+    }
+  }
+
+  // The comment just after the declaration was not a trailing comment.
+  // Let's look at the previous comment.
+  if (Comment == RawComments.begin())
+    return NULL;
+  --Comment;
+
+  // Check that we actually have a non-member Doxygen comment.
+  if (!Comment->isDoxygen() || Comment->isTrailingComment())
+    return NULL;
+
+  // Decompose the end of the comment.
+  std::pair<FileID, unsigned> CommentEndDecomp
+    = SourceMgr.getDecomposedLoc(Comment->getSourceRange().getEnd());
+
+  // If the comment and the declaration aren't in the same file, then they
+  // aren't related.
+  if (DeclLocDecomp.first != CommentEndDecomp.first)
+    return NULL;
+
+  // Get the corresponding buffer.
+  bool Invalid = false;
+  const char *Buffer = SourceMgr.getBufferData(DeclLocDecomp.first,
+                                               &Invalid).data();
+  if (Invalid)
+    return NULL;
+
+  // Extract text between the comment and declaration.
+  StringRef Text(Buffer + CommentEndDecomp.second,
+                 DeclLocDecomp.second - CommentEndDecomp.second);
+
+  // There should be no other declarations between comment and declaration.
+  if (Text.find_first_of(",;{}") != StringRef::npos)
+    return NULL;
+
+  return &*Comment;
+}
+
+const RawComment *ASTContext::getRawCommentForDecl(const Decl *D) const {
+  // Check whether we have cached a comment string for this declaration
+  // already.
+  llvm::DenseMap<const Decl *, const RawComment *>::iterator Pos
+      = DeclComments.find(D);
+  if (Pos != DeclComments.end())
+      return Pos->second;
+
+  const RawComment *RC = getRawCommentForDeclNoCache(D);
+  DeclComments[D] = RC;
+  return RC;
+}
+
 void 
 ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, 
                                                TemplateTemplateParmDecl *Parm) {
@@ -244,6 +345,7 @@
     BuiltinInfo(builtins),
     DeclarationNames(*this),
     ExternalSource(0), Listener(0),
+    Comments(SM), CommentsLoaded(false),
     LastSDM(0, 0),
     UniqueBlockByRefTypeID(0) 
 {

Modified: cfe/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CMakeLists.txt?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/CMakeLists.txt (original)
+++ cfe/trunk/lib/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -15,3 +15,4 @@
 add_subdirectory(FrontendTool)
 add_subdirectory(Tooling)
 add_subdirectory(StaticAnalyzer)
+add_subdirectory(Comments)

Added: cfe/trunk/lib/Comments/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Comments/CMakeLists.txt?rev=158771&view=auto
==============================================================================
--- cfe/trunk/lib/Comments/CMakeLists.txt (added)
+++ cfe/trunk/lib/Comments/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -0,0 +1,7 @@
+set(LLVM_USED_LIBS clangBasic clangAST clangLex)
+
+add_clang_library(clangComments
+  CommentLexer.cpp
+  RawCommentList.cpp
+  )
+

Added: cfe/trunk/lib/Comments/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Comments/Makefile?rev=158771&view=auto
==============================================================================
--- cfe/trunk/lib/Comments/Makefile (added)
+++ cfe/trunk/lib/Comments/Makefile Tue Jun 19 19:34:58 2012
@@ -0,0 +1,14 @@
+##===- clang/lib/Comments/Makefile -------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+LIBRARYNAME := clangComments
+
+include $(CLANG_LEVEL)/Makefile
+

Added: cfe/trunk/lib/Comments/RawCommentList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Comments/RawCommentList.cpp?rev=158771&view=auto
==============================================================================
--- cfe/trunk/lib/Comments/RawCommentList.cpp (added)
+++ cfe/trunk/lib/Comments/RawCommentList.cpp Tue Jun 19 19:34:58 2012
@@ -0,0 +1,207 @@
+//===--- RawCommentList.cpp - Processing raw comments -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Comments/RawCommentList.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+
+namespace {
+/// Get comment kind and bool describing if it is a trailing comment.
+std::pair<RawComment::CommentKind, bool> getCommentKind(StringRef Comment) {
+  if (Comment.size() < 3 || Comment[0] != '/')
+    return std::make_pair(RawComment::CK_Invalid, false);
+
+  RawComment::CommentKind K;
+  if (Comment[1] == '/') {
+    if (Comment.size() < 3)
+      return std::make_pair(RawComment::CK_OrdinaryBCPL, false);
+
+    if (Comment[2] == '/')
+      K = RawComment::CK_BCPLSlash;
+    else if (Comment[2] == '!')
+      K = RawComment::CK_BCPLExcl;
+    else
+      return std::make_pair(RawComment::CK_OrdinaryBCPL, false);
+  } else {
+    assert(Comment.size() >= 4);
+
+    // Comment lexer does not understand escapes in comment markers, so pretend
+    // that this is not a comment.
+    if (Comment[1] != '*' ||
+        Comment[Comment.size() - 2] != '*' ||
+        Comment[Comment.size() - 1] != '/')
+      return std::make_pair(RawComment::CK_Invalid, false);
+
+    if (Comment[2] == '*')
+      K = RawComment::CK_JavaDoc;
+    else if (Comment[2] == '!')
+      K = RawComment::CK_Qt;
+    else
+      return std::make_pair(RawComment::CK_OrdinaryC, false);
+  }
+  const bool TrailingComment = (Comment.size() > 3) && (Comment[3] == '<');
+  return std::make_pair(K, TrailingComment);
+}
+
+bool mergedCommentIsTrailingComment(StringRef Comment) {
+  return (Comment.size() > 3) && (Comment[3] == '<');
+}
+} // unnamed namespace
+
+RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR,
+                       bool Merged) :
+    Range(SR), RawTextValid(false), IsAlmostTrailingComment(false),
+    BeginLineValid(false), EndLineValid(false) {
+  // Extract raw comment text, if possible.
+  if (getRawText(SourceMgr).empty()) {
+    Kind = CK_Invalid;
+    return;
+  }
+
+  if (!Merged) {
+    // Guess comment kind.
+    std::pair<CommentKind, bool> K = getCommentKind(RawText);
+    Kind = K.first;
+    IsTrailingComment = K.second;
+
+    IsAlmostTrailingComment = RawText.startswith("//<") ||
+                                 RawText.startswith("/*<");
+  } else {
+    Kind = CK_Merged;
+    IsTrailingComment = mergedCommentIsTrailingComment(RawText);
+  }
+}
+
+unsigned RawComment::getBeginLine(const SourceManager &SM) const {
+  if (BeginLineValid)
+    return BeginLine;
+
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin());
+  BeginLine = SM.getLineNumber(LocInfo.first, LocInfo.second);
+  BeginLineValid = true;
+  return BeginLine;
+}
+
+unsigned RawComment::getEndLine(const SourceManager &SM) const {
+  if (EndLineValid)
+    return EndLine;
+
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getEnd());
+  EndLine = SM.getLineNumber(LocInfo.first, LocInfo.second);
+  EndLineValid = true;
+  return EndLine;
+}
+
+StringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const {
+  FileID BeginFileID;
+  FileID EndFileID;
+  unsigned BeginOffset;
+  unsigned EndOffset;
+
+  llvm::tie(BeginFileID, BeginOffset) =
+      SourceMgr.getDecomposedLoc(Range.getBegin());
+  llvm::tie(EndFileID, EndOffset) =
+      SourceMgr.getDecomposedLoc(Range.getEnd());
+
+  const unsigned Length = EndOffset - BeginOffset;
+  if (Length < 2)
+    return StringRef();
+
+  // The comment can't begin in one file and end in another.
+  assert(BeginFileID == EndFileID);
+
+  bool Invalid = false;
+  const char *BufferStart = SourceMgr.getBufferData(BeginFileID,
+                                                    &Invalid).data();
+  if (Invalid)
+    return StringRef();
+
+  return StringRef(BufferStart + BeginOffset, Length);
+}
+
+namespace {
+bool containsOnlyWhitespace(StringRef Str) {
+  return Str.find_first_not_of(" \t\f\v\r\n") == StringRef::npos;
+}
+
+bool onlyWhitespaceBetweenComments(SourceManager &SM,
+                                   const RawComment &C1, const RawComment &C2) {
+  std::pair<FileID, unsigned> C1EndLocInfo = SM.getDecomposedLoc(
+                                                C1.getSourceRange().getEnd());
+  std::pair<FileID, unsigned> C2BeginLocInfo = SM.getDecomposedLoc(
+                                              C2.getSourceRange().getBegin());
+
+  // Question does not make sense if comments are located in different files.
+  if (C1EndLocInfo.first != C2BeginLocInfo.first)
+    return false;
+
+  bool Invalid = false;
+  const char *Buffer = SM.getBufferData(C1EndLocInfo.first, &Invalid).data();
+  if (Invalid)
+    return false;
+
+  StringRef TextBetweenComments(Buffer + C1EndLocInfo.second,
+                                C2BeginLocInfo.second - C1EndLocInfo.second);
+
+  return containsOnlyWhitespace(TextBetweenComments);
+}
+} // unnamed namespace
+
+void RawCommentList::addComment(const RawComment &RC, ASTContext &Context) {
+  if (RC.isInvalid())
+    return;
+
+  assert((Comments.empty() ||
+          SourceMgr.isBeforeInTranslationUnit(
+              Comments[0].getSourceRange().getEnd(),
+              RC.getSourceRange().getBegin())) &&
+         "comments are not coming in source order");
+
+  if (OnlyWhitespaceSeen) {
+    if (!onlyWhitespaceBetweenComments(SourceMgr, LastComment, RC))
+      OnlyWhitespaceSeen = false;
+  }
+
+  LastComment = RC;
+
+  // Ordinary comments are not interesting for us.
+  if (RC.isOrdinary())
+    return;
+
+  // If this is the first Doxygen comment, save it (because there isn't
+  // anything to merge it with).
+  if (Comments.empty()) {
+    Comments.push_back(RC);
+    OnlyWhitespaceSeen = true;
+    return;
+  }
+
+  const RawComment &C1 = Comments.back();
+  const RawComment &C2 = RC;
+
+  // Merge comments only if there is only whitespace between them.
+  // Can't merge trailing and non-trailing comments.
+  // Merge trailing comments if they are on same or consecutive lines.
+  if (OnlyWhitespaceSeen &&
+      (C1.isTrailingComment() == C2.isTrailingComment()) &&
+      (!C1.isTrailingComment() ||
+       C1.getEndLine(SourceMgr) + 1 >= C2.getBeginLine(SourceMgr))) {
+    SourceRange MergedRange(C1.getSourceRange().getBegin(),
+                            C2.getSourceRange().getEnd());
+    RawComment Merged(SourceMgr, MergedRange, true);
+    Comments.pop_back();
+    Comments.push_back(Merged);
+  } else
+    Comments.push_back(RC);
+
+  OnlyWhitespaceSeen = true;
+}
+

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Tue Jun 19 19:34:58 2012
@@ -623,14 +623,14 @@
                                      /*IsIncludeDirective=*/false);
 }
 
-void Preprocessor::AddCommentHandler(CommentHandler *Handler) {
+void Preprocessor::addCommentHandler(CommentHandler *Handler) {
   assert(Handler && "NULL comment handler");
   assert(std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler) ==
          CommentHandlers.end() && "Comment handler already registered");
   CommentHandlers.push_back(Handler);
 }
 
-void Preprocessor::RemoveCommentHandler(CommentHandler *Handler) {
+void Preprocessor::removeCommentHandler(CommentHandler *Handler) {
   std::vector<CommentHandler *>::iterator Pos
   = std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler);
   assert(Pos != CommentHandlers.end() && "Comment handler not registered");

Modified: cfe/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Makefile (original)
+++ cfe/trunk/lib/Makefile Tue Jun 19 19:34:58 2012
@@ -10,7 +10,7 @@
 
 PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \
                 StaticAnalyzer Edit Rewrite ARCMigrate Serialization Frontend \
-                FrontendTool Tooling Driver
+                FrontendTool Tooling Driver Comments
 
 include $(CLANG_LEVEL)/Makefile
 

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Jun 19 19:34:58 2012
@@ -23,6 +23,20 @@
 #include "clang/AST/ASTConsumer.h"
 using namespace clang;
 
+/// \brief A comment handler that passes comments found by the preprocessor
+/// to the parser action.
+class ActionCommentHandler : public CommentHandler {
+  Sema &S;
+
+public:
+  explicit ActionCommentHandler(Sema &S) : S(S) { }
+
+  virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) {
+    S.ActOnComment(Comment);
+    return false;
+  }
+};
+
 IdentifierInfo *Parser::getSEHExceptKeyword() {
   // __except is accepted as a (contextual) keyword 
   if (!Ident__except && (getLangOpts().MicrosoftExt || getLangOpts().Borland))
@@ -77,7 +91,10 @@
 
     PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
   }
-      
+
+  CommentHandler.reset(new ActionCommentHandler(actions));
+  PP.addCommentHandler(CommentHandler.get());
+
   PP.setCodeCompletionHandler(*this);
 }
 
@@ -422,6 +439,9 @@
 
   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
   FPContractHandler.reset();
+
+  PP.removeCommentHandler(CommentHandler.get());
+
   PP.clearCodeCompletionHandler();
 
   assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Tue Jun 19 19:34:58 2012
@@ -1014,6 +1014,11 @@
   return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());  
 }
 
+void Sema::ActOnComment(SourceRange Comment) {
+  RawComment RC(SourceMgr, Comment);
+  Context.addComment(RC);
+}
+
 // Pin this vtable to this file.
 ExternalSemaSource::~ExternalSemaSource() {}
 

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Jun 19 19:34:58 2012
@@ -2550,7 +2550,7 @@
         //  RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
         if (!RemovalLocs.empty()) {
           std::sort(RemovalLocs.begin(), RemovalLocs.end(),
-                    SourceManager::LocBeforeThanCompare(S.getSourceManager()));
+                    BeforeThanCompare<SourceLocation>(S.getSourceManager()));
           RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
           Loc = RemovalLocs.front();
         }

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Jun 19 19:34:58 2012
@@ -1737,6 +1737,17 @@
         }
         break;
 
+      case COMMENTS_BLOCK_ID: {
+        llvm::BitstreamCursor C = Stream;
+        if (Stream.SkipBlock() ||
+            ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
+          Error("malformed comments block in AST file");
+          return Failure;
+        }
+        CommentsCursors.push_back(std::make_pair(C, &F));
+        break;
+      }
+
       default:
         if (!Stream.SkipBlock())
           break;
@@ -6258,6 +6269,61 @@
   CurrSwitchCaseStmts->clear();
 }
 
+void ASTReader::ReadComments() {
+  std::vector<RawComment> Comments;
+  for (SmallVectorImpl<std::pair<llvm::BitstreamCursor,
+                                 serialization::ModuleFile *> >::iterator
+       I = CommentsCursors.begin(),
+       E = CommentsCursors.end();
+       I != E; ++I) {
+    llvm::BitstreamCursor &Cursor = I->first;
+    serialization::ModuleFile &F = *I->second;
+    SavedStreamPosition SavedPosition(Cursor);
+
+    RecordData Record;
+    while (true) {
+      unsigned Code = Cursor.ReadCode();
+      if (Code == llvm::bitc::END_BLOCK)
+        break;
+
+      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+        // No known subblocks, always skip them.
+        Cursor.ReadSubBlockID();
+        if (Cursor.SkipBlock()) {
+          Error("malformed block record in AST file");
+          return;
+        }
+        continue;
+      }
+
+      if (Code == llvm::bitc::DEFINE_ABBREV) {
+        Cursor.ReadAbbrevRecord();
+        continue;
+      }
+
+      // Read a record.
+      Record.clear();
+      switch ((CommentRecordTypes) Cursor.ReadRecord(Code, Record)) {
+        default:  // Default behavior: ignore.
+          break;
+
+        case COMMENTS_RAW_COMMENT: {
+          unsigned Idx = 0;
+          SourceRange SR = ReadSourceRange(F, Record, Idx);
+          RawComment::CommentKind Kind =
+              (RawComment::CommentKind) Record[Idx++];
+          bool IsTrailingComment = Record[Idx++];
+          bool IsAlmostTrailingComment = Record[Idx++];
+          Comments.push_back(RawComment(SR, Kind, IsTrailingComment,
+                                        IsAlmostTrailingComment));
+          break;
+      }
+      }
+    }
+  }
+  Context.Comments.addCommentsToFront(Comments);
+}
+
 void ASTReader::finishPendingActions() {
   while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty()) {
     // If any identifiers with corresponding top-level declarations have

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Jun 19 19:34:58 2012
@@ -2240,6 +2240,23 @@
   Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs));
 }
 
+void ASTWriter::WriteComments() {
+  Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3);
+  ArrayRef<RawComment> RawComments = Context->Comments.getComments();
+  RecordData Record;
+  for (ArrayRef<RawComment>::iterator I = RawComments.begin(),
+                                      E = RawComments.end();
+       I != E; ++I) {
+    Record.clear();
+    AddSourceRange(I->getSourceRange(), Record);
+    Record.push_back(I->getKind());
+    Record.push_back(I->isTrailingComment());
+    Record.push_back(I->isAlmostTrailingComment());
+    Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record);
+  }
+  Stream.ExitBlock();
+}
+
 //===----------------------------------------------------------------------===//
 // Global Method Pool and Selector Serialization
 //===----------------------------------------------------------------------===//
@@ -3415,6 +3432,7 @@
 
   WriteFileDeclIDsMap();
   WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+  WriteComments();
   
   if (Chain) {
     // Write the mapping information describing our module dependencies and how

Added: cfe/trunk/test/Index/annotate-comments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-comments.cpp?rev=158771&view=auto
==============================================================================
--- cfe/trunk/test/Index/annotate-comments.cpp (added)
+++ cfe/trunk/test/Index/annotate-comments.cpp Tue Jun 19 19:34:58 2012
@@ -0,0 +1,229 @@
+// Run lines are sensitive to line numbers and come below the code.
+
+#ifndef HEADER
+#define HEADER
+
+// Not a Doxygen comment.  NOT_DOXYGEN
+void notdoxy1(void);
+
+/* Not a Doxygen comment.  NOT_DOXYGEN */
+void notdoxy2(void);
+
+/*/ Not a Doxygen comment.  NOT_DOXYGEN */
+void notdoxy3(void);
+
+/** Doxygen comment.  isdoxy4 IS_DOXYGEN_SINGLE */
+void isdoxy4(void);
+
+/**
+ * Doxygen comment.  isdoxy5 IS_DOXYGEN_SINGLE */
+void isdoxy5(void);
+
+/**
+ * Doxygen comment.
+ * isdoxy6 IS_DOXYGEN_SINGLE */
+void isdoxy6(void);
+
+/**
+ * Doxygen comment.
+ * isdoxy7 IS_DOXYGEN_SINGLE
+ */
+void isdoxy7(void);
+
+/*! Doxygen comment.  isdoxy8 IS_DOXYGEN_SINGLE */
+void isdoxy8(void);
+
+/// Doxygen comment.  isdoxy9 IS_DOXYGEN_SINGLE
+void isdoxy9(void);
+
+// Not a Doxygen comment.  NOT_DOXYGEN
+/// Doxygen comment.  isdoxy10 IS_DOXYGEN_SINGLE
+void isdoxy10(void);
+
+/// Doxygen comment.  isdoxy11 IS_DOXYGEN_SINGLE
+// Not a Doxygen comment.  NOT_DOXYGEN
+void isdoxy11(void);
+
+/** Doxygen comment.  isdoxy12  IS_DOXYGEN_SINGLE */
+/* Not a Doxygen comment.  NOT_DOXYGEN */
+void isdoxy12(void);
+
+/// Doxygen comment.  isdoxy13 IS_DOXYGEN_START
+/// Doxygen comment.  IS_DOXYGEN_END
+void isdoxy13(void);
+
+/// Doxygen comment.  isdoxy14 IS_DOXYGEN_START
+/// Blah-blah-blah.
+/// Doxygen comment.  IS_DOXYGEN_END
+void isdoxy14(void);
+
+/// Doxygen comment.  isdoxy15 IS_DOXYGEN_START
+/** Blah-blah-blah */
+/// Doxygen comment.  IS_DOXYGEN_END
+void isdoxy15(void);
+
+/** Blah-blah-blah. isdoxy16 IS_DOXYGEN_START *//** Blah */
+/// Doxygen comment.  IS_DOXYGEN_END
+void isdoxy16(void);
+
+/// isdoxy17 IS_DOXYGEN_START
+// Not a Doxygen comment, but still picked up.
+/// IS_DOXYGEN_END
+void isdoxy17(void);
+
+unsigned
+// NOT_DOXYGEN
+/// isdoxy18 IS_DOXYGEN_START
+// Not a Doxygen comment, but still picked up.
+/// IS_DOXYGEN_END
+// NOT_DOXYGEN
+int isdoxy18(void);
+
+//! It all starts here. isdoxy19 IS_DOXYGEN_START
+/*! It's a little odd to continue line this,
+ *
+ * but we need more multi-line comments. */
+/// This comment comes before my other comments
+/** This is a block comment that is associated with the function f. It
+ *  runs for three lines.  IS_DOXYGEN_END
+ */
+void isdoxy19(int, int);
+
+// NOT IN THE COMMENT  NOT_DOXYGEN
+/// This is a BCPL comment.  isdoxy20 IS_DOXYGEN_START
+/// It has only two lines.
+/** But there are other blocks that are part of the comment, too.  IS_DOXYGEN_END */
+void isdoxy20(int);
+
+void isdoxy21(int); ///< This is a member comment.  isdoxy21 IS_DOXYGEN_SINGLE
+
+void isdoxy22(int); /*!< This is a member comment.  isdoxy22 IS_DOXYGEN_SINGLE */
+
+void isdoxy23(int); /**< This is a member comment.  isdoxy23 IS_DOXYGEN_SINGLE */
+
+void notdoxy24(int); // NOT_DOXYGEN
+
+/// IS_DOXYGEN_SINGLE
+struct isdoxy25 {
+};
+
+struct test26 {
+  /// IS_DOXYGEN_SINGLE
+  int isdoxy26;
+};
+
+struct test27 {
+  int isdoxy27; ///< IS_DOXYGEN_SINGLE
+};
+
+struct notdoxy28 {
+}; ///< IS_DOXYGEN_NOT_ATTACHED
+
+/// IS_DOXYGEN_SINGLE
+enum isdoxy29 {
+};
+
+enum notdoxy30 {
+}; ///< IS_DOXYGEN_NOT_ATTACHED
+
+/// IS_DOXYGEN_SINGLE
+namespace isdoxy31 {
+};
+
+namespace notdoxy32 {
+}; ///< IS_DOXYGEN_NOT_ATTACHED
+
+class test33 {
+                ///< IS_DOXYGEN_NOT_ATTACHED
+  int isdoxy33; ///< isdoxy33 IS_DOXYGEN_SINGLE
+  int isdoxy34; ///< isdoxy34 IS_DOXYGEN_SINGLE
+
+                ///< IS_DOXYGEN_NOT_ATTACHED
+  int isdoxy35, ///< isdoxy35 IS_DOXYGEN_SINGLE
+      isdoxy36; ///< isdoxy36 IS_DOXYGEN_SINGLE
+
+                ///< IS_DOXYGEN_NOT_ATTACHED
+  int isdoxy37  ///< isdoxy37 IS_DOXYGEN_SINGLE
+    , isdoxy38  ///< isdoxy38 IS_DOXYGEN_SINGLE
+    , isdoxy39; ///< isdoxy39 IS_DOXYGEN_SINGLE
+};
+
+// Verified that Doxygen attaches these.
+
+/// isdoxy40 IS_DOXYGEN_SINGLE
+// NOT_DOXYGEN
+void isdoxy40(int);
+
+unsigned
+/// isdoxy41 IS_DOXYGEN_SINGLE
+// NOT_DOXYGEN
+int isdoxy41(int);
+
+class test42 {
+  int isdoxy42; /* NOT_DOXYGEN */ ///< isdoxy42 IS_DOXYGEN_SINGLE
+};
+
+#endif
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %clang_cc1 -x c++ -emit-pch -o %t/out.pch %s
+// RUN: %clang_cc1 -x c++ -include-pch %t/out.pch -fsyntax-only %s
+
+// RUN: c-index-test -test-load-source all %s > %t/out.c-index-direct
+// RUN: c-index-test -test-load-tu %t/out.pch all > %t/out.c-index-pch
+
+// RUN: FileCheck %s -check-prefix=WRONG < %t/out.c-index-direct
+// RUN: FileCheck %s -check-prefix=WRONG < %t/out.c-index-pch
+
+// Declarations without Doxygen comments should not pick up some Doxygen comments.
+// WRONG-NOT: notdoxy{{.*}}Comment=
+// WRONG-NOT: test{{.*}}Comment=
+
+// Non-Doxygen comments should not be attached to anything.
+// WRONG-NOT: NOT_DOXYGEN
+
+// Some Doxygen comments are not attached to anything.
+// WRONG-NOT: IS_DOXYGEN_NOT_ATTACHED
+
+// Ensure we don't pick up extra comments.
+// WRONG-NOT: IS_DOXYGEN_START{{.*}}IS_DOXYGEN_START
+// WRONG-NOT: IS_DOXYGEN_END{{.*}}IS_DOXYGEN_END
+
+// RUN: FileCheck %s < %t/out.c-index-direct
+// RUN: FileCheck %s < %t/out.c-index-pch
+
+// CHECK: annotate-comments.cpp:16:6: FunctionDecl=isdoxy4:{{.*}} isdoxy4 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:20:6: FunctionDecl=isdoxy5:{{.*}} isdoxy5 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:25:6: FunctionDecl=isdoxy6:{{.*}} isdoxy6 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:31:6: FunctionDecl=isdoxy7:{{.*}} isdoxy7 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:34:6: FunctionDecl=isdoxy8:{{.*}} isdoxy8 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:37:6: FunctionDecl=isdoxy9:{{.*}} isdoxy9 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:41:6: FunctionDecl=isdoxy10:{{.*}} isdoxy10 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:53:6: FunctionDecl=isdoxy13:{{.*}} isdoxy13 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:58:6: FunctionDecl=isdoxy14:{{.*}} isdoxy14 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:63:6: FunctionDecl=isdoxy15:{{.*}} isdoxy15 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:67:6: FunctionDecl=isdoxy16:{{.*}} isdoxy16 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:72:6: FunctionDecl=isdoxy17:{{.*}} isdoxy17 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:80:5: FunctionDecl=isdoxy18:{{.*}} isdoxy18 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:90:6: FunctionDecl=isdoxy19:{{.*}} isdoxy19 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:96:6: FunctionDecl=isdoxy20:{{.*}} isdoxy20 IS_DOXYGEN_START{{.*}} IS_DOXYGEN_END
+// CHECK: annotate-comments.cpp:98:6: FunctionDecl=isdoxy21:{{.*}} isdoxy21 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:100:6: FunctionDecl=isdoxy22:{{.*}} isdoxy22 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:102:6: FunctionDecl=isdoxy23:{{.*}} isdoxy23 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:107:8: StructDecl=isdoxy25:{{.*}} IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:112:7: FieldDecl=isdoxy26:{{.*}} IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:116:7: FieldDecl=isdoxy27:{{.*}} IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:123:6: EnumDecl=isdoxy29:{{.*}} IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:130:11: Namespace=isdoxy31:{{.*}} IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:138:7: FieldDecl=isdoxy33:{{.*}} isdoxy33 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:139:7: FieldDecl=isdoxy34:{{.*}} isdoxy34 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:142:7: FieldDecl=isdoxy35:{{.*}} isdoxy35 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:143:7: FieldDecl=isdoxy36:{{.*}} isdoxy36 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:146:7: FieldDecl=isdoxy37:{{.*}} isdoxy37 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:147:7: FieldDecl=isdoxy38:{{.*}} isdoxy38 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:148:7: FieldDecl=isdoxy39:{{.*}} isdoxy39 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:155:6: FunctionDecl=isdoxy40:{{.*}} isdoxy40 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:160:5: FunctionDecl=isdoxy41:{{.*}} isdoxy41 IS_DOXYGEN_SINGLE
+// CHECK: annotate-comments.cpp:163:7: FieldDecl=isdoxy42:{{.*}} isdoxy42 IS_DOXYGEN_SINGLE
+

Modified: cfe/trunk/tools/arcmt-test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/arcmt-test/CMakeLists.txt?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/arcmt-test/CMakeLists.txt (original)
+++ cfe/trunk/tools/arcmt-test/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -1,5 +1,6 @@
 set(LLVM_USED_LIBS
   clangARCMigrate
+  clangComments
   clangEdit
   clangRewrite
   )

Modified: cfe/trunk/tools/arcmt-test/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/arcmt-test/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/arcmt-test/Makefile (original)
+++ cfe/trunk/tools/arcmt-test/Makefile Tue Jun 19 19:34:58 2012
@@ -19,6 +19,7 @@
 LINK_COMPONENTS := support mc
 USEDLIBS = clangARCMigrate.a clangRewrite.a \
 		 clangFrontend.a clangDriver.a clangSerialization.a clangParse.a \
-		 clangSema.a clangEdit.a clangAnalysis.a clangAST.a clangLex.a clangBasic.a
+		 clangSema.a clangEdit.a clangAnalysis.a clangAST.a clangLex.a clangComments.a \
+		 clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile

Modified: cfe/trunk/tools/c-index-test/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/Makefile (original)
+++ cfe/trunk/tools/c-index-test/Makefile Tue Jun 19 19:34:58 2012
@@ -20,6 +20,7 @@
 LINK_COMPONENTS := support mc
 USEDLIBS = clang.a clangFrontend.a clangDriver.a \
 	   clangSerialization.a clangParse.a clangSema.a \
-	   clangAnalysis.a clangEdit.a clangAST.a clangLex.a clangBasic.a
+	   clangAnalysis.a clangEdit.a clangAST.a clangLex.a clangComments.a \
+	   clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Tue Jun 19 19:34:58 2012
@@ -218,7 +218,9 @@
     CXPlatformAvailability PlatformAvailability[2];
     int NumPlatformAvailability;
     int I;
-    
+    CXString Comment;
+    const char *CommentCString;
+
     ks = clang_getCursorKindSpelling(Cursor.kind);
     string = want_display_name? clang_getCursorDisplayName(Cursor) 
                               : clang_getCursorSpelling(Cursor);
@@ -398,6 +400,22 @@
       if (!clang_equalRanges(CursorExtent, RefNameRange))
         PrintRange(RefNameRange, "RefName");
     }
+
+    Comment = clang_Cursor_getRawCommentText(Cursor);
+    CommentCString = clang_getCString(Comment);
+    if (CommentCString != NULL && CommentCString[0] != '\0') {
+      printf(" Comment=[");
+      for ( ; *CommentCString; ++CommentCString) {
+        if (*CommentCString != '\n')
+          putchar(*CommentCString);
+        else
+          printf("\\n");
+      }
+      printf("]");
+
+      PrintRange(clang_Cursor_getCommentRange(Cursor), "CommentRange");
+    }
+    clang_disposeString(Comment);
   }
 }
 

Modified: cfe/trunk/tools/clang-check/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/CMakeLists.txt?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/clang-check/CMakeLists.txt (original)
+++ cfe/trunk/tools/clang-check/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -1,4 +1,4 @@
-set(LLVM_USED_LIBS clangTooling clangBasic)
+set(LLVM_USED_LIBS clangTooling clangBasic clangComments)
 
 add_clang_executable(clang-check
   ClangCheck.cpp

Modified: cfe/trunk/tools/clang-check/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/clang-check/Makefile (original)
+++ cfe/trunk/tools/clang-check/Makefile Tue Jun 19 19:34:58 2012
@@ -18,7 +18,7 @@
 LINK_COMPONENTS := support mc
 USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \
            clangTooling.a clangParse.a clangSema.a clangAnalysis.a \
-           clangEdit.a clangAST.a clangLex.a clangBasic.a
+           clangEdit.a clangAST.a clangLex.a clangComments.a clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile
 

Modified: cfe/trunk/tools/diagtool/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/CMakeLists.txt?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/CMakeLists.txt (original)
+++ cfe/trunk/tools/diagtool/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -4,6 +4,7 @@
 
 set( LLVM_USED_LIBS
   clangBasic
+  clangComments
   clangLex
   clangSema
   clangFrontend

Modified: cfe/trunk/tools/diagtool/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/diagtool/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/diagtool/Makefile (original)
+++ cfe/trunk/tools/diagtool/Makefile Tue Jun 19 19:34:58 2012
@@ -20,7 +20,7 @@
 
 USEDLIBS = clangFrontend.a clangDriver.a clangSerialization.a clangParse.a \
            clangSema.a clangAnalysis.a clangEdit.a clangAST.a clangLex.a \
-           clangBasic.a
+           clangComments.a clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile
 

Modified: cfe/trunk/tools/driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/CMakeLists.txt?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/driver/CMakeLists.txt (original)
+++ cfe/trunk/tools/driver/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -4,6 +4,7 @@
   clangAnalysis
   clangBasic
   clangCodeGen
+  clangComments
   clangDriver
   clangEdit
   clangFrontend

Modified: cfe/trunk/tools/driver/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/driver/Makefile (original)
+++ cfe/trunk/tools/driver/Makefile Tue Jun 19 19:34:58 2012
@@ -36,7 +36,7 @@
            clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
            clangStaticAnalyzerCore.a \
            clangAnalysis.a clangARCMigrate.a clangRewrite.a \
-           clangEdit.a clangAST.a clangLex.a clangBasic.a
+           clangEdit.a clangAST.a clangLex.a clangComments.a clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile
 

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Jun 19 19:34:58 2012
@@ -5676,7 +5676,35 @@
   InclusionDirective *ID = getCursorInclusionDirective(cursor);
   return (void *)ID->getFile();
 }
-  
+
+CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {
+  if (!clang_isDeclaration(C.kind))
+    return clang_getNullRange();
+
+  const Decl *D = getCursorDecl(C);
+  ASTContext &Context = getCursorContext(C);
+  const RawComment *RC = Context.getRawCommentForDecl(D);
+  if (!RC)
+    return clang_getNullRange();
+
+  return cxloc::translateSourceRange(Context, RC->getSourceRange());
+}
+
+CXString clang_Cursor_getRawCommentText(CXCursor C) {
+  if (!clang_isDeclaration(C.kind))
+    return createCXString((const char *) NULL);
+
+  const Decl *D = getCursorDecl(C);
+  ASTContext &Context = getCursorContext(C);
+  const RawComment *RC = Context.getRawCommentForDecl(D);
+  StringRef RawText = RC ? RC->getRawText(Context.getSourceManager()) :
+                           StringRef();
+
+  // Don't duplicate the string because RawText points directly into source
+  // code.
+  return createCXString(RawText, false);
+}
+
 } // end: extern "C"
 
 

Modified: cfe/trunk/tools/libclang/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CMakeLists.txt?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CMakeLists.txt (original)
+++ cfe/trunk/tools/libclang/CMakeLists.txt Tue Jun 19 19:34:58 2012
@@ -6,6 +6,7 @@
   clangSerialization
   clangSema
   clangEdit
+  clangComments
   clangAST
   clangLex
   clangBasic)

Modified: cfe/trunk/tools/libclang/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/Makefile (original)
+++ cfe/trunk/tools/libclang/Makefile Tue Jun 19 19:34:58 2012
@@ -19,7 +19,7 @@
 USEDLIBS = clangARCMigrate.a clangRewrite.a clangFrontend.a clangDriver.a \
      clangSerialization.a \
 		 clangParse.a clangSema.a clangEdit.a clangAnalysis.a \
-		 clangAST.a clangLex.a clangBasic.a
+		 clangAST.a clangLex.a clangComments.a clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile
 

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Tue Jun 19 19:34:58 2012
@@ -5,6 +5,8 @@
 clang_CXXMethod_isStatic
 clang_CXXMethod_isVirtual
 clang_Cursor_getArgument
+clang_Cursor_getCommentRange
+clang_Cursor_getRawCommentText
 clang_Cursor_getNumArguments
 clang_Cursor_getObjCSelectorIndex
 clang_Cursor_getSpellingNameRange

Modified: cfe/trunk/unittests/Frontend/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Frontend/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/unittests/Frontend/Makefile (original)
+++ cfe/trunk/unittests/Frontend/Makefile Tue Jun 19 19:34:58 2012
@@ -14,6 +14,6 @@
            clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \
            clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
            clangARCMigrate.a clangRewrite.a clangEdit.a \
-           clangAnalysis.a clangAST.a clangLex.a clangBasic.a
+           clangAnalysis.a clangAST.a clangLex.a clangComments.a clangBasic.a
 
 include $(CLANG_LEVEL)/unittests/Makefile

Modified: cfe/trunk/unittests/Tooling/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/Makefile?rev=158771&r1=158770&r2=158771&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/Makefile (original)
+++ cfe/trunk/unittests/Tooling/Makefile Tue Jun 19 19:34:58 2012
@@ -12,6 +12,6 @@
 LINK_COMPONENTS := support mc
 USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
            clangParse.a clangRewrite.a clangSema.a clangAnalysis.a clangEdit.a \
-           clangAST.a clangLex.a clangBasic.a
+           clangAST.a clangLex.a clangComments.a clangBasic.a
 
 include $(CLANG_LEVEL)/unittests/Makefile





More information about the cfe-commits mailing list