[cfe-commits] r113545 - in /cfe/trunk: include/clang-c/Index.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-ctor-inits.cpp test/Index/load-stmts.cpp tools/libclang/CIndex.cpp tools/libclang/CXCursor.cpp tools/libclang/CXCursor.h

Douglas Gregor dgregor at apple.com
Thu Sep 9 14:42:20 PDT 2010


Author: dgregor
Date: Thu Sep  9 16:42:20 2010
New Revision: 113545

URL: http://llvm.org/viewvc/llvm-project?rev=113545&view=rev
Log:
Teach libclang to walk the base and member initializers of a
constructor, in source order. Also introduces a new reference kind for
class members, which is used here (for member initializers) and will
also be used for designated initializers and offsetof.

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-ctor-inits.cpp
    cfe/trunk/test/Index/load-stmts.cpp
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp
    cfe/trunk/tools/libclang/CXCursor.h

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Sep  9 16:42:20 2010
@@ -1027,15 +1027,20 @@
   CXCursor_TypeRef                       = 43,
   CXCursor_CXXBaseSpecifier              = 44,
   /** 
-   * \brief A reference to a class template, function template, or template
-   * template parameter. 
+   * \brief A reference to a class template, function template, template
+   * template parameter, or class template partial specialization.
    */
   CXCursor_TemplateRef                   = 45,
   /**
    * \brief A reference to a namespace or namespace alias.
    */
   CXCursor_NamespaceRef                  = 46,
-  CXCursor_LastRef                       = CXCursor_NamespaceRef,
+  /**
+   * A reference to a member of a struct, union, or class that occurs in some
+   * non-expression context, e.g., a designated initializer.
+   */
+  CXCursor_MemberRef                     = 47,
+  CXCursor_LastRef                       = CXCursor_MemberRef,
 
   /* Error conditions */
   CXCursor_FirstInvalid                  = 70,

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Sep  9 16:42:20 2010
@@ -3438,7 +3438,8 @@
     Pattern->AddChunk(CodeCompletionString::CK_RightParen);
     Results.AddResult(CodeCompletionResult(Pattern, 
                                    SawLastInitializer? CCP_NextInitializer
-                                                     : CCP_MemberDeclaration));
+                                                     : CCP_MemberDeclaration,
+                                           CXCursor_MemberRef));
     SawLastInitializer = false;
   }
   Results.ExitScope();

Modified: cfe/trunk/test/Index/complete-ctor-inits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-ctor-inits.cpp?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-ctor-inits.cpp (original)
+++ cfe/trunk/test/Index/complete-ctor-inits.cpp Thu Sep  9 16:42:20 2010
@@ -18,23 +18,23 @@
 Z::Z() : ::X<int>(0), Virt(), b(), c() { }
 
 // RUN: c-index-test -code-completion-at=%s:18:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC1: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC1: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
 // CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20)
 // CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (7)
 // CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20)
 
 // RUN: c-index-test -code-completion-at=%s:18:23 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC2: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC2: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
 // CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20)
 // CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (7)
 
 // RUN: c-index-test -code-completion-at=%s:18:36 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC3-NOT: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CC3: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC3: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC3-NOT: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
+// CHECK-CC3: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
 // CHECK-CC3-NOT: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )}
 // CHECK-CC3: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20)

Modified: cfe/trunk/test/Index/load-stmts.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-stmts.cpp?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/test/Index/load-stmts.cpp (original)
+++ cfe/trunk/test/Index/load-stmts.cpp Thu Sep  9 16:42:20 2010
@@ -91,6 +91,19 @@
   (void)__has_nothrow_assign(type);
 }
 
+struct Base {
+  Base(int);
+};
+
+struct Derived : public Base {
+  Derived(int x);
+  int member;
+};
+
+Derived::Derived(int x) 
+  : member(x), Base(x) {
+}
+
 // RUN: c-index-test -test-load-source all %s | FileCheck %s
 // CHECK: load-stmts.cpp:1:13: TypedefDecl=T:1:13 (Definition) Extent=[1:13 - 1:14]
 // CHECK: load-stmts.cpp:2:8: StructDecl=X:2:8 (Definition) Extent=[2:1 - 2:23]
@@ -198,3 +211,12 @@
 // CHECK: load-stmts.cpp:90:17: DeclRefExpr=y:88:44 Extent=[90:17 - 90:18]
 // CHECK: load-stmts.cpp:91:9: UnexposedExpr= Extent=[91:9 - 91:35]
 // CHECK: load-stmts.cpp:91:30: TypeRef=type:89:13 Extent=[91:30 - 91:34]
+// CHECK: load-stmts.cpp:103:10: CXXConstructor=Derived:103:10 (Definition)
+// CHECK: load-stmts.cpp:103:1: TypeRef=struct Derived:98:8 Extent=[103:1 - 103:
+// FIXME: Missing TypeRef for constructor name.
+// CHECK: load-stmts.cpp:103:22: ParmDecl=x:103:22 (Definition) 
+// CHECK: load-stmts.cpp:104:5: MemberRef=member:100:7 Extent=[104:5 - 104:11]
+// CHECK: load-stmts.cpp:104:12: DeclRefExpr=x:103:22 Extent=[104:12 - 104:13]
+// CHECK: load-stmts.cpp:104:16: TypeRef=struct Base:94:8 Extent=[104:16 - 104:2
+// CHECK: load-stmts.cpp:104:16: CallExpr= Extent=[104:16 - 104:22]
+// CHECK: load-stmts.cpp:104:21: DeclRefExpr=x:103:22 Extent=[104:21 - 104:22]

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Thu Sep  9 16:42:20 2010
@@ -30,6 +30,7 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Timer.h"
@@ -697,6 +698,21 @@
   return false;
 }
 
+/// \brief Compare two base or member initializers based on their source order.
+static int CompareCXXBaseOrMemberInitializers(const void* Xp, const void *Yp) {
+  CXXBaseOrMemberInitializer const * const *X
+    = static_cast<CXXBaseOrMemberInitializer const * const *>(Xp);
+  CXXBaseOrMemberInitializer const * const *Y
+    = static_cast<CXXBaseOrMemberInitializer const * const *>(Yp);
+  
+  if ((*X)->getSourceOrder() < (*Y)->getSourceOrder())
+    return -1;
+  else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder())
+    return 1;
+  else
+    return 0;
+}
+
 bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
   if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
     // Visit the function declaration's syntactic components in the order
@@ -729,9 +745,45 @@
     // FIXME: Attributes?
   }
   
-  if (ND->isThisDeclarationADefinition() &&
-      Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
-    return true;
+  if (ND->isThisDeclarationADefinition()) {
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
+      // Find the initializers that were written in the source.
+      llvm::SmallVector<CXXBaseOrMemberInitializer *, 4> WrittenInits;
+      for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(),
+                                          IEnd = Constructor->init_end();
+           I != IEnd; ++I) {
+        if (!(*I)->isWritten())
+          continue;
+      
+        WrittenInits.push_back(*I);
+      }
+      
+      // Sort the initializers in source order
+      llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
+                           &CompareCXXBaseOrMemberInitializers);
+      
+      // Visit the initializers in source order
+      for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
+        CXXBaseOrMemberInitializer *Init = WrittenInits[I];
+        if (Init->isMemberInitializer()) {
+          if (Visit(MakeCursorMemberRef(Init->getMember(), 
+                                        Init->getMemberLocation(), TU)))
+            return true;
+        } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) {
+          if (Visit(BaseInfo->getTypeLoc()))
+            return true;
+        }
+        
+        // Visit the initializer value.
+        if (Expr *Initializer = Init->getInit())
+          if (Visit(MakeCXCursor(Initializer, ND, TU)))
+            return true;
+      } 
+    }
+    
+    if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+      return true;
+  }
 
   return false;
 }
@@ -2485,6 +2537,13 @@
       return createCXString(NS->getNameAsString());
     }
 
+    case CXCursor_MemberRef: {
+      FieldDecl *Field = getCursorMemberRef(C).first;
+      assert(Field && "Missing member decl");
+      
+      return createCXString(Field->getNameAsString());
+    }
+
     default:
       return createCXString("<not implemented>");
     }
@@ -2567,6 +2626,8 @@
       return createCXString("TemplateRef");
   case CXCursor_NamespaceRef:
     return createCXString("NamespaceRef");
+  case CXCursor_MemberRef:
+    return createCXString("MemberRef");
   case CXCursor_UnexposedExpr:
       return createCXString("UnexposedExpr");
   case CXCursor_BlockExpr:
@@ -2769,6 +2830,11 @@
       return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
     }
 
+    case CXCursor_MemberRef: {
+      std::pair<FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
+      return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+    }
+
     case CXCursor_CXXBaseSpecifier: {
       // FIXME: Figure out what location to return for a CXXBaseSpecifier.
       return clang_getNullLocation();
@@ -2832,7 +2898,10 @@
 
     case CXCursor_NamespaceRef:
       return getCursorNamespaceRef(C).second;
-        
+
+    case CXCursor_MemberRef:
+      return getCursorMemberRef(C).second;
+
     case CXCursor_CXXBaseSpecifier:
       // FIXME: Figure out what source range to use for a CXBaseSpecifier.
       return SourceRange();
@@ -2916,6 +2985,9 @@
     case CXCursor_NamespaceRef:
       return MakeCXCursor(getCursorNamespaceRef(C).first, CXXUnit);
 
+    case CXCursor_MemberRef:
+      return MakeCXCursor(getCursorMemberRef(C).first, CXXUnit);
+
     case CXCursor_CXXBaseSpecifier: {
       CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
       return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Thu Sep  9 16:42:20 2010
@@ -291,6 +291,23 @@
                                        reinterpret_cast<uintptr_t>(C.data[1])));  
 }
 
+CXCursor cxcursor::MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc, 
+                                       ASTUnit *TU) {
+  
+  assert(Field && TU && "Invalid arguments!");
+  void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+  CXCursor C = { CXCursor_MemberRef, { Field, RawLoc, TU } };
+  return C;    
+}
+
+std::pair<FieldDecl *, SourceLocation> 
+cxcursor::getCursorMemberRef(CXCursor C) {
+  assert(C.kind == CXCursor_MemberRef);
+  return std::make_pair(static_cast<FieldDecl *>(C.data[0]),
+                        SourceLocation::getFromRawEncoding(
+                                       reinterpret_cast<uintptr_t>(C.data[1])));  
+}
+
 CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU){
   CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } };
   return C;  

Modified: cfe/trunk/tools/libclang/CXCursor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.h?rev=113545&r1=113544&r2=113545&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.h (original)
+++ cfe/trunk/tools/libclang/CXCursor.h Thu Sep  9 16:42:20 2010
@@ -26,6 +26,7 @@
 class CXXBaseSpecifier;
 class Decl;
 class Expr;
+class FieldDecl;
 class MacroDefinition;
 class MacroInstantiation;
 class NamedDecl;
@@ -93,6 +94,14 @@
 /// it references and the location where the reference occurred.
 std::pair<NamedDecl *, SourceLocation> getCursorNamespaceRef(CXCursor C);
 
+/// \brief Create a reference to a field at the given location.
+CXCursor MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc, 
+                             ASTUnit *TU);
+  
+/// \brief Unpack a MemberRef cursor into the field it references and the 
+/// location where the reference occurred.
+std::pair<FieldDecl *, SourceLocation> getCursorMemberRef(CXCursor C);
+
 /// \brief Create a CXX base specifier cursor.
 CXCursor MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU);
 





More information about the cfe-commits mailing list