[cfe-commits] r98421 - in /cfe/trunk: include/clang-c/Index.h tools/CIndex/CIndex.exports tools/CIndex/CIndexUSRs.cpp

Ted Kremenek kremenek at apple.com
Fri Mar 12 18:50:35 PST 2010


Author: kremenek
Date: Fri Mar 12 20:50:34 2010
New Revision: 98421

URL: http://llvm.org/viewvc/llvm-project?rev=98421&view=rev
Log:
Implement several CIndex functions for constructing USRs from C-strings instead of AST elements.

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/tools/CIndex/CIndex.exports
    cfe/trunk/tools/CIndex/CIndexUSRs.cpp

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=98421&r1=98420&r2=98421&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Mar 12 20:50:34 2010
@@ -171,7 +171,7 @@
  */
 CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
                                          int displayDiagnostics);
-  
+
 /**
  * \brief Destroy the given index.
  *
@@ -297,7 +297,7 @@
  * \brief Retrieve a NULL (invalid) source range.
  */
 CINDEX_LINKAGE CXSourceRange clang_getNullRange();
-  
+
 /**
  * \brief Retrieve a source range given the beginning and ending source
  * locations.
@@ -357,11 +357,11 @@
  */
 enum CXDiagnosticSeverity {
   /**
-   * \brief A diagnostic that has been suppressed, e.g., by a command-line 
+   * \brief A diagnostic that has been suppressed, e.g., by a command-line
    * option.
    */
   CXDiagnostic_Ignored = 0,
-  
+
   /**
    * \brief This diagnostic is a note that should be attached to the
    * previous (non-note) diagnostic.
@@ -451,7 +451,7 @@
    * diagnostic, also include information about source ranges in a
    * machine-parsable format.
    *
-   * This option corresponds to the clang flag 
+   * This option corresponds to the clang flag
    * \c -fdiagnostics-print-source-range-info.
    */
   CXDiagnostic_DisplaySourceRanges = 0x04
@@ -461,13 +461,13 @@
  * \brief Format the given diagnostic in a manner that is suitable for display.
  *
  * This routine will format the given diagnostic to a string, rendering
- * the diagnostic according to the various options given. The 
- * \c clang_defaultDiagnosticDisplayOptions() function returns the set of 
+ * the diagnostic according to the various options given. The
+ * \c clang_defaultDiagnosticDisplayOptions() function returns the set of
  * options that most closely mimics the behavior of the clang compiler.
  *
  * \param Diagnostic The diagnostic to print.
  *
- * \param Options A set of options that control the diagnostic display, 
+ * \param Options A set of options that control the diagnostic display,
  * created by combining \c CXDiagnosticDisplayOptions values.
  *
  * \returns A new string containing for formatted diagnostic.
@@ -491,7 +491,7 @@
 /**
  * \brief Determine the severity of the given diagnostic.
  */
-CINDEX_LINKAGE enum CXDiagnosticSeverity 
+CINDEX_LINKAGE enum CXDiagnosticSeverity
 clang_getDiagnosticSeverity(CXDiagnostic);
 
 /**
@@ -512,21 +512,21 @@
  * diagnostic.
  */
 CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
-  
+
 /**
  * \brief Retrieve a source range associated with the diagnostic.
  *
  * A diagnostic's source ranges highlight important elements in the source
  * code. On the command line, Clang displays source ranges by
- * underlining them with '~' characters. 
+ * underlining them with '~' characters.
  *
  * \param Diagnostic the diagnostic whose range is being extracted.
  *
- * \param Range the zero-based index specifying which range to 
+ * \param Range the zero-based index specifying which range to
  *
  * \returns the requested source range.
  */
-CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, 
+CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
                                                       unsigned Range);
 
 /**
@@ -560,7 +560,7 @@
  * \returns A string containing text that should be replace the source
  * code indicated by the \c ReplacementRange.
  */
-CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, 
+CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
                                                  unsigned FixIt,
                                                CXSourceRange *ReplacementRange);
 
@@ -577,7 +577,7 @@
  *
  * @{
  */
-  
+
 /**
  * \brief Get the original translation unit source file name.
  */
@@ -625,22 +625,22 @@
                                          const char **clang_command_line_args,
                                          unsigned num_unsaved_files,
                                          struct CXUnsavedFile *unsaved_files);
- 
+
 /**
  * \brief Create a translation unit from an AST file (-emit-ast).
  */
-CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, 
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
                                              const char *ast_filename);
 
 /**
  * \brief Destroy the specified CXTranslationUnit object.
  */
 CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
- 
+
 /**
  * @}
  */
-  
+
 /**
  * \brief Describes the kind of entity that a cursor refers to.
  */
@@ -1083,6 +1083,47 @@
 CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor);
 
 /**
+ * \brief Construct a USR for a specified Objective-C class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name);
+
+/**
+ * \brief Construct a USR for a specified Objective-C category.
+ */
+CINDEX_LINKAGE CXString
+  clang_constructUSR_ObjCategory(const char *class_name,
+                                 const char *category_name);
+
+/**
+ * \brief Construct a USR for a specified Objective-C protocol.
+ */
+CINDEX_LINKAGE CXString
+  clang_constructUSR_ObjCProtocol(const char *protocol_name);
+
+
+/**
+ * \brief Construct a USR for a specified Objective-C instance variable and
+ *   the USR for its containing class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name,
+                                                    CXString classUSR);
+
+/**
+ * \brief Construct a USR for a specified Objective-C method and
+ *   the USR for its containing class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name,
+                                                      unsigned isInstanceMethod,
+                                                      CXString classUSR);
+
+/**
+ * \brief Construct a USR for a specified Objective-C property and the USR
+ *  for its containing class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property,
+                                                        CXString classUSR);
+
+/**
  * \brief Retrieve a name for the entity referenced by this cursor.
  */
 CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
@@ -1157,22 +1198,22 @@
    * \brief A token that contains some kind of punctuation.
    */
   CXToken_Punctuation,
-  
+
   /**
    * \brief A language keyword.
    */
   CXToken_Keyword,
-  
+
   /**
    * \brief An identifier (that is not a keyword).
    */
   CXToken_Identifier,
-  
+
   /**
    * \brief A numeric, string, or character literal.
    */
   CXToken_Literal,
-  
+
   /**
    * \brief A comment.
    */
@@ -1191,7 +1232,7 @@
  * \brief Determine the kind of the given token.
  */
 CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
-  
+
 /**
  * \brief Determine the spelling of the given token.
  *
@@ -1199,13 +1240,13 @@
  * the text of an identifier or keyword.
  */
 CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
-  
+
 /**
  * \brief Retrieve the source location of the given token.
  */
-CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit, 
+CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
                                                        CXToken);
-  
+
 /**
  * \brief Retrieve a source range that covers the given token.
  */
@@ -1230,7 +1271,7 @@
  */
 CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
                                    CXToken **Tokens, unsigned *NumTokens);
-  
+
 /**
  * \brief Annotate the given set of tokens by providing cursors for each token
  * that can be mapped to a specific entity within the abstract syntax tree.
@@ -1264,17 +1305,17 @@
 CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU,
                                          CXToken *Tokens, unsigned NumTokens,
                                          CXCursor *Cursors);
-  
+
 /**
  * \brief Free the given set of tokens.
  */
-CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU, 
+CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU,
                                         CXToken *Tokens, unsigned NumTokens);
-  
+
 /**
  * @}
  */
-  
+
 /**
  * \defgroup CINDEX_DEBUG Debugging facilities
  *
@@ -1689,7 +1730,7 @@
  * \brief Determine the number of diagnostics produced prior to the
  * location where code completion was performed.
  */
-CINDEX_LINKAGE 
+CINDEX_LINKAGE
 unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
 
 /**
@@ -1701,7 +1742,7 @@
  * \returns the requested diagnostic. This diagnostic must be freed
  * via a call to \c clang_disposeDiagnostic().
  */
-CINDEX_LINKAGE 
+CINDEX_LINKAGE
 CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
                                              unsigned Index);
 
@@ -1726,10 +1767,10 @@
  * \brief Return a version string, suitable for showing to a user, but not
  *        intended to be parsed (the format is not guaranteed to be stable).
  */
- 
- 
+
+
  /**
-  * \brief Visitor invoked for each file in a translation unit 
+  * \brief Visitor invoked for each file in a translation unit
   *        (used with clang_getInclusions()).
   *
   * This visitor function will be invoked by clang_getInclusions() for each

Modified: cfe/trunk/tools/CIndex/CIndex.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.exports?rev=98421&r1=98420&r2=98421&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.exports (original)
+++ cfe/trunk/tools/CIndex/CIndex.exports Fri Mar 12 20:50:34 2010
@@ -2,6 +2,12 @@
 _clang_codeComplete
 _clang_codeCompleteGetDiagnostic
 _clang_codeCompleteGetNumDiagnostics
+_clang_constructUSR_ObjCClass
+_clang_constructUSR_ObjCategory
+_clang_constructUSR_ObjCIvar
+_clang_constructUSR_ObjCMethod
+_clang_constructUSR_ObjCProtocol
+_clang_constructUSR_ObjCProperty
 _clang_createIndex
 _clang_createTranslationUnit
 _clang_createTranslationUnitFromSourceFile

Modified: cfe/trunk/tools/CIndex/CIndexUSRs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexUSRs.cpp?rev=98421&r1=98420&r2=98421&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndexUSRs.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndexUSRs.cpp Fri Mar 12 20:50:34 2010
@@ -29,23 +29,77 @@
   bool IgnoreResults;
 public:
   USRGenerator(llvm::raw_ostream &out) : Out(out), IgnoreResults(false) {}
-  
+
   bool ignoreResults() const { return IgnoreResults; }
-  
+
+  // Visitation methods from generating USRs from AST elements.
   void VisitBlockDecl(BlockDecl *D);
   void VisitDeclContext(DeclContext *D);
   void VisitFieldDecl(FieldDecl *D);
   void VisitFunctionDecl(FunctionDecl *D);
   void VisitNamedDecl(NamedDecl *D);
   void VisitNamespaceDecl(NamespaceDecl *D);
-  void VisitObjCContainerDecl(ObjCContainerDecl *CD);  
+  void VisitObjCContainerDecl(ObjCContainerDecl *CD);
   void VisitObjCMethodDecl(ObjCMethodDecl *MD);
   void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
   void VisitTagDecl(TagDecl *D);
   void VisitTypedefDecl(TypedefDecl *D);
+
+
+  /// String generation methods used both by the visitation methods
+  /// and from other clients that want to directly generate USRs.  These
+  /// methods do not construct complete USRs (which incorporate the parents
+  /// of an AST element), but only the fragments concerning the AST element
+  /// itself.
+
+  /// Generate a USR fragment for a named declaration.  This does
+  /// not include the USR component for the parent.
+  void GenNamedDecl(llvm::StringRef name);
+
+  /// Generate a USR for an Objective-C class.
+  void GenObjCClass(llvm::StringRef cls);
+  /// Generate a USR for an Objective-C class category.
+  void GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat);
+  /// Generate a USR fragment for an Objective-C instance variable.  The
+  /// complete USR can be created by concatenating the USR for the
+  /// encompassing class with this USR fragment.
+  void GenObjCIvar(llvm::StringRef ivar);
+  /// Generate a USR fragment for an Objective-C method.
+  void GenObjCMethod(llvm::StringRef sel, bool isInstanceMethod);
+  /// Generate a USR fragment for an Objective-C property.
+  void GenObjCProperty(llvm::StringRef prop);
+  /// Generate a USR for an Objective-C protocol.
+  void GenObjCProtocol(llvm::StringRef prot);
+};
+
+class StringUSRGenerator {
+private:
+  llvm::SmallString<1024> StrBuf;
+  llvm::raw_svector_ostream Out;
+  USRGenerator UG;
+public:
+  StringUSRGenerator()
+    : Out(StrBuf), UG(Out) {}
+
+  llvm::StringRef str() {
+    return Out.str();
+  }
+
+  USRGenerator* operator->() { return &UG; }
+
+  template <typename T>
+  llvm::raw_svector_ostream &operator<<(const T &x) {
+    Out << x;
+    return Out;
+  }
 };
+
 } // end anonymous namespace
 
+//===----------------------------------------------------------------------===//
+// Generating USRs from ASTS.
+//===----------------------------------------------------------------------===//
+
 void USRGenerator::VisitBlockDecl(BlockDecl *D) {
   VisitDeclContext(D->getDeclContext());
   // FIXME: Better support for anonymous blocks.
@@ -76,8 +130,8 @@
 void USRGenerator::VisitNamedDecl(NamedDecl *D) {
   VisitDeclContext(D->getDeclContext());
   const std::string &s = D->getNameAsString();
-//  assert(!s.empty());
-  Out << "@^" << s;
+  //  assert(!s.empty());
+  GenNamedDecl(s);
 }
 
 void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
@@ -87,8 +141,8 @@
 
 void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
   Visit(cast<Decl>(D->getDeclContext()));
-  Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
-  Out << DeclarationName(D->getSelector()).getAsString();
+  GenObjCMethod(DeclarationName(D->getSelector()).getAsString(),
+                D->isInstanceMethod());
 }
 
 void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
@@ -97,29 +151,29 @@
       assert(false && "Invalid ObjC container.");
     case Decl::ObjCInterface:
     case Decl::ObjCImplementation:
-      Out << "objc(cs)" << D->getName();
+      GenObjCClass(D->getName());
       break;
     case Decl::ObjCCategory: {
       ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
-      Out << "objc(cy)" << CD->getClassInterface()->getName()
-      << '^' << CD->getName();
+      GenObjCCategory(CD->getClassInterface()->getName(),
+                      CD->getName());
       break;
     }
     case Decl::ObjCCategoryImpl: {
       ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
-      Out << "objc(cy)" << CD->getClassInterface()->getName()
-      << '^' << CD->getName();
+      GenObjCCategory(CD->getClassInterface()->getName(),
+                      CD->getName());
       break;
     }
     case Decl::ObjCProtocol:
-      Out << "objc(pl)" << cast<ObjCProtocolDecl>(D)->getName();
+      GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
       break;
   }
 }
 
 void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
   Visit(cast<Decl>(D->getDeclContext()));
-  Out << "(py)" << D->getName();
+  GenObjCProperty(D->getName());
 }
 
 void USRGenerator::VisitTagDecl(TagDecl *D) {
@@ -130,12 +184,12 @@
     case TagDecl::TK_union:  Out << "@U^"; break;
     case TagDecl::TK_enum:   Out << "@E^"; break;
   }
-  
+
   // FIXME: Better support for anonymous structures and enums.
   const std::string &s = D->getNameAsString();
   if (s.empty()) {
     if (TypedefDecl *TD = D->getTypedefForAnonDecl())
-      Out << "^anontd^" << TD->getNameAsString();    
+      Out << "^anontd^" << TD->getNameAsString();
     else
       Out << "^anon";
   }
@@ -146,36 +200,104 @@
 void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
   DeclContext *DC = D->getDeclContext();
   if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
-    Visit(DCN);  
+    Visit(DCN);
   Out << "typedef@" << D->getName();
 }
 
-// FIXME: This is a skeleton implementation.  It will be overhauled.
-static CXString ConstructUSR(Decl *D) {
-  llvm::SmallString<1024> StrBuf;
-  {
-    llvm::raw_svector_ostream Out(StrBuf);
-    USRGenerator UG(Out);
-    UG.Visit(static_cast<Decl*>(D));
-    if (UG.ignoreResults())
-      return createCXString(NULL);
-  }
-  
-  if (StrBuf.empty())
-    return createCXString(NULL);
-  
-  // Return a copy of the string that must be disposed by the caller.
-  return createCXString(StrBuf.str(), true);
-}  
+//===----------------------------------------------------------------------===//
+// General purpose USR generation methods.
+//===----------------------------------------------------------------------===//
+
+void USRGenerator::GenNamedDecl(llvm::StringRef name) {
+  Out << "@^" << name;
+}
+
+void USRGenerator::GenObjCClass(llvm::StringRef cls) {
+  Out << "objc(cs)" << cls;
+}
+
+void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) {
+  Out << "objc(cy)" << cls << '^' << cat;
+}
 
+void USRGenerator::GenObjCIvar(llvm::StringRef ivar) {
+  GenNamedDecl(ivar);
+}
+
+void USRGenerator::GenObjCMethod(llvm::StringRef meth, bool isInstanceMethod) {
+  Out << (isInstanceMethod ? "(im)" : "(cm)") << meth;
+}
+
+void USRGenerator::GenObjCProperty(llvm::StringRef prop) {
+  Out << "(py)" << prop;
+}
+
+void USRGenerator::GenObjCProtocol(llvm::StringRef prot) {
+  Out << "objc(pl)" << prot;
+}
+
+//===----------------------------------------------------------------------===//
+// API hooks.
+//===----------------------------------------------------------------------===//
 
 extern "C" {
 
 CXString clang_getCursorUSR(CXCursor C) {
-  if (Decl *D = cxcursor::getCursorDecl(C))
-    return ConstructUSR(D);  
-  
-  return createCXString(NULL);
+  Decl *D = cxcursor::getCursorDecl(C);
+  if (!D)
+    return createCXString(NULL);
+
+  StringUSRGenerator SUG;
+  SUG->Visit(static_cast<Decl*>(D));
+
+  if (SUG->ignoreResults() || SUG.str().empty())
+    return createCXString(NULL);
+
+  // Return a copy of the string that must be disposed by the caller.
+  return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
+  StringUSRGenerator SUG;
+  SUG << clang_getCString(classUSR);
+  SUG->GenObjCIvar(name);
+  return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCMethod(const char *name,
+                                       unsigned isInstanceMethod,
+                                       CXString classUSR) {
+  StringUSRGenerator SUG;
+  SUG << clang_getCString(classUSR);
+  SUG->GenObjCMethod(name, isInstanceMethod);
+  return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCClass(const char *name) {
+  StringUSRGenerator SUG;
+  SUG->GenObjCClass(name);
+  return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCProtocol(const char *name) {
+  StringUSRGenerator SUG;
+  SUG->GenObjCProtocol(name);
+  return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCategory(const char *class_name,
+                                        const char *category_name) {
+  StringUSRGenerator SUG;
+  SUG->GenObjCCategory(class_name, category_name);
+  return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCProperty(const char *property,
+                                         CXString classUSR) {
+  StringUSRGenerator SUG;
+  SUG << clang_getCString(classUSR);
+  SUG->GenObjCProperty(property);
+  return createCXString(SUG.str(), true);
 }
 
 } // end extern "C"





More information about the cfe-commits mailing list