[cfe-commits] r112604 - in /cfe/trunk: include/clang-c/Index.h include/clang/AST/DeclTemplate.h lib/Sema/SemaTemplate.cpp test/Index/index-templates.cpp tools/libclang/CIndex.cpp tools/libclang/CIndexUSRs.cpp tools/libclang/CXCursor.cpp

Douglas Gregor dgregor at apple.com
Tue Aug 31 10:01:40 PDT 2010


Author: dgregor
Date: Tue Aug 31 12:01:39 2010
New Revision: 112604

URL: http://llvm.org/viewvc/llvm-project?rev=112604&view=rev
Log:
Implement basic support for indexing function templates in
libclang. This includes:
  - Cursor kind for function templates, with visitation logic
  - Cursor kinds for template parameters, with visitation logic
  - Visitation logic for template specialization types, qualified type
  locations
  - USR generation for function templates, template specialization
  types, template parameter types.

Also happens to fix PR7804, which I tripped across while testing.

Added:
    cfe/trunk/test/Index/index-templates.cpp   (with props)
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CIndexUSRs.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=112604&r1=112603&r2=112604&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue Aug 31 12:01:39 2010
@@ -982,8 +982,16 @@
   CXCursor_Destructor                    = 25,
   /** \brief A C++ conversion function. */
   CXCursor_ConversionFunction            = 26,
+  /** \brief A C++ template type parameter. */
+  CXCursor_TemplateTypeParameter         = 27,
+  /** \brief A C++ non-type template parameter. */
+  CXCursor_NonTypeTemplateParameter      = 28,
+  /** \brief A C++ template template parameter. */
+  CXCursor_TemplateTemplateParameter     = 29,
+  /** \brief A C++ function template. */
+  CXCursor_FunctionTemplate              = 30,
   CXCursor_FirstDecl                     = CXCursor_UnexposedDecl,
-  CXCursor_LastDecl                      = CXCursor_ConversionFunction,
+  CXCursor_LastDecl                      = CXCursor_FunctionTemplate,
 
   /* References */
   CXCursor_FirstRef                      = 40, /* Decl references */

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=112604&r1=112603&r2=112604&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Aug 31 12:01:39 2010
@@ -1138,6 +1138,13 @@
     DefaultArgumentWasInherited = false;
   }
 
+  SourceRange getSourceRange() const {
+    SourceLocation End = getLocation();
+    if (hasDefaultArgument() && !defaultArgumentWasInherited())
+      End = getDefaultArgument().getSourceRange().getEnd();
+    return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
+  }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const TemplateTemplateParmDecl *D) { return true; }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=112604&r1=112603&r2=112604&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Aug 31 12:01:39 2010
@@ -662,7 +662,8 @@
   // Construct the parameter object.
   TemplateTemplateParmDecl *Param =
     TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
-                                     TmpLoc, Depth, Position, Name,
+                                     NameLoc.isInvalid()? TmpLoc : NameLoc, 
+                                     Depth, Position, Name,
                                      (TemplateParameterList*)Params);
 
   // If the template template parameter has a name, then link the identifier 

Added: cfe/trunk/test/Index/index-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/index-templates.cpp?rev=112604&view=auto
==============================================================================
--- cfe/trunk/test/Index/index-templates.cpp (added)
+++ cfe/trunk/test/Index/index-templates.cpp Tue Aug 31 12:01:39 2010
@@ -0,0 +1,22 @@
+// Test is line- and column-sensitive. See run lines below.
+
+template<typename T, T Value, template<typename U, U ValU> class X>
+void f(X<T, Value> x);
+
+// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-LOAD %s
+// CHECK-LOAD: index-templates.cpp:4:6: FunctionTemplate=f:4:6 Extent=[3:1 - 4:22]
+// CHECK-LOAD: index-templates.cpp:3:19: TemplateTypeParameter=T:3:19 (Definition) Extent=[3:19 - 3:20]
+// CHECK-LOAD: index-templates.cpp:3:24: NonTypeTemplateParameter=Value:3:24 (Definition) Extent=[3:22 - 3:29]
+// FIXME: Need the template type parameter here
+// CHECK-LOAD: index-templates.cpp:3:66: TemplateTemplateParameter=X:3:66 (Definition) Extent=[3:31 - 3:67]
+// CHECK-LOAD: index-templates.cpp:4:20: ParmDecl=x:4:20 (Definition) Extent=[4:8 - 4:21]
+// FIXME: Need the template declaration here.
+// FIXME: Need the template type parameter here
+// CHECK-LOAD: index-templates.cpp:4:13: DeclRefExpr=Value:3:24 Extent=[4:13 - 4:18]
+
+// RUN: c-index-test -test-load-source-usrs all %s | FileCheck -check-prefix=CHECK-USRS %s
+// CHECK-USRS: index-templates.cpp c:@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0# Extent=[3:1 - 4:22]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp at 79 Extent=[3:19 - 3:20]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp at 82 Extent=[3:22 - 3:29]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp at 91 Extent=[3:31 - 3:67]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp at 136@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0#@x Extent=[4:8 - 4:21]

Propchange: cfe/trunk/test/Index/index-templates.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Index/index-templates.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Index/index-templates.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=112604&r1=112603&r2=112604&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Aug 31 12:01:39 2010
@@ -290,11 +290,13 @@
   bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
   bool VisitTypedefDecl(TypedefDecl *D);
   bool VisitTagDecl(TagDecl *D);
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
   bool VisitEnumConstantDecl(EnumConstantDecl *D);
   bool VisitDeclaratorDecl(DeclaratorDecl *DD);
   bool VisitFunctionDecl(FunctionDecl *ND);
   bool VisitFieldDecl(FieldDecl *D);
   bool VisitVarDecl(VarDecl *);
+  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
   bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
   bool VisitObjCContainerDecl(ObjCContainerDecl *D);
   bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
@@ -311,17 +313,21 @@
   bool VisitObjCClassDecl(ObjCClassDecl *D);
   bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
   bool VisitNamespaceDecl(NamespaceDecl *D);
-
+ 
   // Name visitor
   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
   
+  // Template visitors
+  bool VisitTemplateParameters(const TemplateParameterList *Params);
+  bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
+  
   // Type visitors
   bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
   bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
   bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
   bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
   bool VisitTagTypeLoc(TagTypeLoc TL);
-  // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
+  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL);
   bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
   bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
   bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
@@ -332,7 +338,7 @@
   bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
   bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
   bool VisitArrayTypeLoc(ArrayTypeLoc TL);
-  // FIXME: Implement for TemplateSpecializationTypeLoc
+  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL);
   // FIXME: Implement visitors here when the unimplemented TypeLocs get
   // implemented
   bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
@@ -593,6 +599,11 @@
   return VisitDeclContext(D);
 }
 
+bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+  // FIXME: Visit default argument
+  return false;
+}
+
 bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
   if (Expr *Init = D->getInitExpr())
     return Visit(MakeCXCursor(Init, StmtParent, TU));
@@ -663,6 +674,15 @@
   return false;
 }
 
+bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
+  // before visiting these template parameters.
+  if (VisitTemplateParameters(D->getTemplateParameters()))
+    return true;
+  
+  return VisitFunctionDecl(D->getTemplatedDecl());
+}
+
 bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
   if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
     if (Visit(TSInfo->getTypeLoc()))
@@ -839,6 +859,54 @@
   return false;
 }
 
+bool CursorVisitor::VisitTemplateParameters(
+                                          const TemplateParameterList *Params) {
+  if (!Params)
+    return false;
+  
+  for (TemplateParameterList::const_iterator P = Params->begin(),
+                                          PEnd = Params->end();
+       P != PEnd; ++P) {
+    if (Visit(MakeCXCursor(*P, TU)))
+      return true;
+  }
+  
+  return false;
+}
+
+bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
+  switch (TAL.getArgument().getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+    return false;
+      
+  case TemplateArgument::Pack:
+    // FIXME: Implement when variadic templates come along.
+    return false;
+
+  case TemplateArgument::Type:
+    if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
+      return Visit(TSInfo->getTypeLoc());
+    return false;
+      
+  case TemplateArgument::Declaration:
+    if (Expr *E = TAL.getSourceDeclExpression())
+      return Visit(MakeCXCursor(E, StmtParent, TU));
+    return false;
+      
+  case TemplateArgument::Expression:
+    if (Expr *E = TAL.getSourceExpression())
+      return Visit(MakeCXCursor(E, StmtParent, TU));
+    return false;
+  
+  case TemplateArgument::Template:
+    // FIXME: Visit template name.
+    return false;
+  }
+  
+  return false;
+}
+
 bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
   return VisitDeclContext(D);
 }
@@ -918,6 +986,13 @@
   return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
 }
 
+bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+  // FIXME: We can't visit the template template parameter, but there's
+  // no context information with which we can match up the depth/index in the
+  // type to the appropriate 
+  return false;
+}
+
 bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
   if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
     return true;
@@ -985,6 +1060,18 @@
   return false;
 }
 
+bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
+                                             TemplateSpecializationTypeLoc TL) {
+  // FIXME: Visit the template name.
+  
+  // Visit the template arguments.
+  for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+    if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+      return true;
+  
+  return false;
+}
+
 bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
   return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
 }
@@ -2037,6 +2124,14 @@
     return createCXString("CXXDestructor");
   case CXCursor_ConversionFunction:
     return createCXString("CXXConversion");
+  case CXCursor_TemplateTypeParameter:
+    return createCXString("TemplateTypeParameter");
+  case CXCursor_NonTypeTemplateParameter:
+    return createCXString("NonTypeTemplateParameter");
+  case CXCursor_TemplateTemplateParameter:
+    return createCXString("TemplateTemplateParameter");
+  case CXCursor_FunctionTemplate:
+    return createCXString("FunctionTemplate");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");

Modified: cfe/trunk/tools/libclang/CIndexUSRs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexUSRs.cpp?rev=112604&r1=112603&r2=112604&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexUSRs.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexUSRs.cpp Tue Aug 31 12:01:39 2010
@@ -13,6 +13,7 @@
 
 #include "CIndexer.h"
 #include "CXCursor.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Lex/PreprocessingRecord.h"
@@ -64,6 +65,7 @@
   void VisitFunctionDecl(FunctionDecl *D);
   void VisitNamedDecl(NamedDecl *D);
   void VisitNamespaceDecl(NamespaceDecl *D);
+  void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
   void VisitObjCClassDecl(ObjCClassDecl *CD);
   void VisitObjCContainerDecl(ObjCContainerDecl *CD);
   void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P);
@@ -72,7 +74,10 @@
   void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
   void VisitTagDecl(TagDecl *D);
   void VisitTypedefDecl(TypedefDecl *D);
+  void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
   void VisitVarDecl(VarDecl *D);
+  void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+  void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
   void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
     IgnoreResults = true;
     return;
@@ -104,7 +109,10 @@
   void GenObjCProtocol(llvm::StringRef prot);
 
   void VisitType(QualType T);
-
+  void VisitTemplateParameterList(const TemplateParameterList *Params);
+  void VisitTemplateName(TemplateName Name);
+  void VisitTemplateArgument(const TemplateArgument &Arg);
+  
   /// Emit a Decl's name using NamedDecl::printName() and return true if
   ///  the decl had no name.
   bool EmitDeclName(const NamedDecl *D);
@@ -155,7 +163,11 @@
     return;
 
   VisitDeclContext(D->getDeclContext());
-  Out << "@F@";
+  if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
+    Out << "@FT@";
+    VisitTemplateParameterList(FunTmpl->getTemplateParameters());
+  } else
+    Out << "@F@";
   D->printName(Out);
 
   ASTContext &Ctx = AU->getASTContext();
@@ -215,6 +227,16 @@
     Out << '@' << s;
 }
 
+void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+  GenLoc(D);
+  return;
+}
+
+void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+  GenLoc(D);
+  return;
+}
+
 void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
   if (D->isAnonymousNamespace()) {
     Out << "@aN";
@@ -226,6 +248,10 @@
     Out << "@N@" << D->getName();
 }
 
+void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  VisitFunctionDecl(D->getTemplatedDecl());
+}
+
 void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
   Decl *container = cast<Decl>(D->getDeclContext());
   
@@ -366,6 +392,11 @@
   Out << D->getName();
 }
 
+void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+  GenLoc(D);
+  return;
+}
+
 bool USRGenerator::GenLoc(const Decl *D) {
   if (generatedLoc)
     return IgnoreResults;
@@ -515,13 +546,100 @@
       VisitTagDecl(TT->getDecl());
       return;
     }
-
+    if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
+      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+      return;
+    }
+    if (const TemplateSpecializationType *Spec
+                                    = T->getAs<TemplateSpecializationType>()) {
+      Out << '>';
+      VisitTemplateName(Spec->getTemplateName());
+      Out << Spec->getNumArgs();
+      for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+        VisitTemplateArgument(Spec->getArg(I));
+      return;
+    }
+    
     // Unhandled type.
     Out << ' ';
     break;
   } while (true);
 }
 
+void USRGenerator::VisitTemplateParameterList(
+                                         const TemplateParameterList *Params) {
+  if (!Params)
+    return;
+  Out << '>' << Params->size();
+  for (TemplateParameterList::const_iterator P = Params->begin(),
+                                          PEnd = Params->end();
+       P != PEnd; ++P) {
+    Out << '#';
+    if (isa<TemplateTypeParmDecl>(*P)) {
+      Out << 'T';
+      continue;
+    }
+    
+    if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+      Out << 'N';
+      VisitType(NTTP->getType());
+      continue;
+    }
+    
+    TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+    Out << 't';
+    VisitTemplateParameterList(TTP->getTemplateParameters());
+  }
+}
+
+void USRGenerator::VisitTemplateName(TemplateName Name) {
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    if (TemplateTemplateParmDecl *TTP
+                              = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+      return;
+    }
+    
+    Visit(Template);
+    return;
+  }
+  
+  // FIXME: Visit dependent template names.
+}
+
+void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    break;
+
+  case TemplateArgument::Declaration:
+    Visit(Arg.getAsDecl());
+    break;
+      
+  case TemplateArgument::Template:
+    VisitTemplateName(Arg.getAsTemplate());
+    break;
+      
+  case TemplateArgument::Expression:
+    // FIXME: Visit expressions.
+    break;
+      
+  case TemplateArgument::Pack:
+    // FIXME: Variadic templates
+    break;
+      
+  case TemplateArgument::Type:
+    VisitType(Arg.getAsType());
+    break;
+      
+  case TemplateArgument::Integral:
+    Out << 'V';
+    VisitType(Arg.getIntegralType());
+    Out << *Arg.getAsIntegral();
+    break;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // General purpose USR generation methods.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=112604&r1=112603&r2=112604&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Aug 31 12:01:39 2010
@@ -60,6 +60,10 @@
     case Decl::Typedef:            return CXCursor_TypedefDecl;
     case Decl::Var:                return CXCursor_VarDecl;
     case Decl::Namespace:          return CXCursor_Namespace;
+    case Decl::TemplateTypeParm:   return CXCursor_TemplateTypeParameter;
+    case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
+    case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
+    case Decl::FunctionTemplate:   return CXCursor_FunctionTemplate;
     default:
       if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
         switch (TD->getTagKind()) {





More information about the cfe-commits mailing list