]> granicus.if.org Git - clang/commitdiff
[index] Add indexing for unresolved-using declarations
authorBen Langmuir <blangmuir@apple.com>
Wed, 16 Aug 2017 23:12:21 +0000 (23:12 +0000)
committerBen Langmuir <blangmuir@apple.com>
Wed, 16 Aug 2017 23:12:21 +0000 (23:12 +0000)
In dependent contexts we end up referencing these, so make sure they
have USRs, and have their declarations indexed. For the most part they
behave like typedefs, but we also need to worry about having multiple
using declarations with the same "name".

rdar://problem/33883650

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311053 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Index/IndexSymbol.h
lib/Index/IndexDecl.cpp
lib/Index/IndexSymbol.cpp
lib/Index/USRGeneration.cpp
test/Index/Core/index-dependent-source.cpp
test/Index/index-templates.cpp
tools/libclang/CXIndexDataConsumer.cpp

index abb132f9e4ce8a45ae28dd0fbc81d58c7074554e..ae591364f229ed6c1884bce873a24d3bd65e75c2 100644 (file)
@@ -53,6 +53,7 @@ enum class SymbolKind : uint8_t {
   ConversionFunction,
 
   Parameter,
+  Using,
 };
 
 enum class SymbolLanguage {
@@ -69,6 +70,8 @@ enum class SymbolSubKind {
   CXXMoveConstructor,
   AccessorGetter,
   AccessorSetter,
+  UsingTypename,
+  UsingValue,
 };
 
 /// Set of properties that provide additional info about a symbol.
index fe6beef6705b5a5d5409adc0667ec2b06adeda2e..ee28ef737d9976444fd74822f6b2aa4d443febfe 100644 (file)
@@ -611,6 +611,24 @@ public:
                                     SymbolRoleSet());
   }
 
+  bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
+    TRY_DECL(D, IndexCtx.handleDecl(D));
+    const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+    const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+                                         D->getLexicalDeclContext());
+    return true;
+  }
+
+  bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
+    TRY_DECL(D, IndexCtx.handleDecl(D));
+    const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+    const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+                                         D->getLexicalDeclContext());
+    return true;
+  }
+
   bool VisitClassTemplateSpecializationDecl(const
                                            ClassTemplateSpecializationDecl *D) {
     // FIXME: Notify subsequent callbacks if info comes from implicit
index 95b3ac19666170d20bfaa4f95e936732e31bdead..03db0cd53f7a56d224a77dfe4955c69d293e4533 100644 (file)
@@ -300,6 +300,18 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
       Info.Kind = SymbolKind::TypeAlias;
       Info.Lang = SymbolLanguage::CXX;
       break;
+    case Decl::UnresolvedUsingTypename:
+      Info.Kind = SymbolKind::Using;
+      Info.SubKind = SymbolSubKind::UsingTypename;
+      Info.Lang = SymbolLanguage::CXX;
+      Info.Properties |= (unsigned)SymbolProperty::Generic;
+      break;
+    case Decl::UnresolvedUsingValue:
+      Info.Kind = SymbolKind::Using;
+      Info.SubKind = SymbolSubKind::UsingValue;
+      Info.Lang = SymbolLanguage::CXX;
+      Info.Properties |= (unsigned)SymbolProperty::Generic;
+      break;
     case Decl::Binding:
       Info.Kind = SymbolKind::Variable;
       Info.Lang = SymbolLanguage::CXX;
@@ -448,6 +460,7 @@ StringRef index::getSymbolKindString(SymbolKind K) {
   case SymbolKind::Destructor: return "destructor";
   case SymbolKind::ConversionFunction: return "coversion-func";
   case SymbolKind::Parameter: return "param";
+  case SymbolKind::Using: return "using";
   }
   llvm_unreachable("invalid symbol kind");
 }
@@ -459,6 +472,8 @@ StringRef index::getSymbolSubKindString(SymbolSubKind K) {
   case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor";
   case SymbolSubKind::AccessorGetter: return "acc-get";
   case SymbolSubKind::AccessorSetter: return "acc-set";
+  case SymbolSubKind::UsingTypename: return "using-typename";
+  case SymbolSubKind::UsingValue: return "using-value";
   }
   llvm_unreachable("invalid symbol subkind");
 }
index 21054b099a8e79da0f8214770eb15b7d2b2e45ec..c4fe737e511f57ed3764034e514674775daaf7ae 100644 (file)
@@ -99,6 +99,8 @@ public:
   void VisitVarDecl(const VarDecl *D);
   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
+  void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
+  void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
 
   void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
     IgnoreResults = true;
@@ -112,14 +114,6 @@ public:
     IgnoreResults = true;
   }
 
-  void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
-    IgnoreResults = true;
-  }
-
-  void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
-    IgnoreResults = true;
-  }
-
   bool ShouldGenerateLocation(const NamedDecl *D);
 
   bool isLocal(const NamedDecl *D) {
@@ -609,6 +603,16 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
   return IgnoreResults;
 }
 
+static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
+  // FIXME: Encode the qualifier, don't just print it.
+  PrintingPolicy PO(Ctx.getLangOpts());
+  PO.SuppressTagKeyword = true;
+  PO.SuppressUnwrittenScope = true;
+  PO.ConstantArraySizeAsWritten = false;
+  PO.AnonymousTagLocations = false;
+  NNS->print(Out, PO);
+}
+
 void USRGenerator::VisitType(QualType T) {
   // This method mangles in USR information for types.  It can possibly
   // just reuse the naming-mangling logic used by codegen, although the
@@ -797,13 +801,7 @@ void USRGenerator::VisitType(QualType T) {
     }
     if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
       Out << '^';
-      // FIXME: Encode the qualifier, don't just print it.
-      PrintingPolicy PO(Ctx.getLangOpts());
-      PO.SuppressTagKeyword = true;
-      PO.SuppressUnwrittenScope = true;
-      PO.ConstantArraySizeAsWritten = false;
-      PO.AnonymousTagLocations = false;
-      DNT->getQualifier()->print(Out, PO);
+      printQualifier(Out, Ctx, DNT->getQualifier());
       Out << ':' << DNT->getIdentifier()->getName();
       return;
     }
@@ -912,6 +910,26 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
   }
 }
 
+void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
+  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+    return;
+  VisitDeclContext(D->getDeclContext());
+  Out << "@UUV@";
+  printQualifier(Out, D->getASTContext(), D->getQualifier());
+  EmitDeclName(D);
+}
+
+void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
+  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+    return;
+  VisitDeclContext(D->getDeclContext());
+  Out << "@UUT@";
+  printQualifier(Out, D->getASTContext(), D->getQualifier());
+  Out << D->getName(); // Simple name.
+}
+
+
+
 //===----------------------------------------------------------------------===//
 // USR generation functions.
 //===----------------------------------------------------------------------===//
index 59c6286cd3dd9e9ce66249878c9d0dfee5a18f6b..2e111339af6124bfbbed64bcdeddc3ef0d6f6438 100644 (file)
@@ -158,3 +158,69 @@ void infiniteTraitRecursion(Trait<T> &t) {
 // Shouldn't crash!
   t.lookup;
 }
+
+template <typename T>
+struct UsingA {
+// CHECK: [[@LINE+1]]:15 | type-alias/C | Type | c:index-dependent-source.cpp@ST>1#T@UsingA@T@Type | <no-cgname> | Def,RelChild | rel: 1
+  typedef int Type;
+// CHECK: [[@LINE+1]]:15 | static-method/C++ | func | c:@ST>1#T@UsingA@F@func#S | <no-cgname> | Decl,RelChild | rel: 1
+  static void func();
+// CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator() | c:@ST>1#T@UsingA@F@operator()#I# | <no-cgname> | Decl,RelChild | rel: 1
+  void operator()(int);
+// CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator+ | c:@ST>1#T@UsingA@F@operator+#&1>@ST>1#T@UsingA1t0.0# | <no-cgname> | Decl,RelChild | rel: 1
+  void operator+(const UsingA &);
+};
+
+template <typename T>
+struct OtherUsing {};
+
+template <typename T>
+struct UsingB : public UsingA<T> {
+// CHECK: [[@LINE+2]]:40 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | <no-cgname> | Def,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:20 | struct(Gen)/C++ | OtherUsing | c:@ST>1#T@OtherUsing | <no-cgname> | Ref,RelCont | rel: 1
+  typedef typename OtherUsing<T>::Type TypeB;
+// CHECK: [[@LINE+2]]:29 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA<T>::Type | <no-cgname> | Decl,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:18 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
+  using typename UsingA<T>::Type;
+// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::func | <no-cgname> | Decl,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
+  using UsingA<T>::func;
+
+// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator() | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::operator() | <no-cgname> | Decl,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
+  using UsingA<T>::operator();
+// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator+ | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::operator+ | <no-cgname> | Decl,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
+  using UsingA<T>::operator+;
+};
+
+template <typename T>
+struct UsingC : public UsingB<T> {
+  static void test() {
+// CHECK: [[@LINE+2]]:25 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | <no-cgname> | Ref,RelCont | rel: 1
+    typename UsingB<T>::TypeB value1;
+// CHECK: [[@LINE+2]]:25 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA<T>::Type | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | <no-cgname> | Ref,RelCont | rel: 1
+    typename UsingB<T>::Type value2;
+// CHECK: [[@LINE+2]]:16 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::func | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
+// CHECK: [[@LINE+1]]:5 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | <no-cgname> | Ref,RelCont | rel: 1
+    UsingB<T>::func();
+  }
+};
+
+template <typename T>
+struct UsingD {
+// CHECK: [[@LINE+1]]:8 | instance-method/C++ | foo | c:@ST>1#T@UsingD@F@foo#t0.0# | <no-cgname> | Decl,RelChild | rel: 1
+  void foo(T);
+};
+
+template <typename T, typename U>
+struct UsingE : public UsingD<T>, public UsingD<U> {
+// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD<T>::foo | <no-cgname> | Decl,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | <no-cgname> | Ref,RelCont | rel: 1
+  using UsingD<T>::foo;
+// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD<U>::foo | <no-cgname> | Decl,RelChild | rel: 1
+// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | <no-cgname> | Ref,RelCont | rel: 1
+  using UsingD<U>::foo;
+};
index 966cc4f5ea7fe2bf70588d661fa4bc29756159b3..424a638ffbb8fa258038c9fbb08392decd87b332 100644 (file)
@@ -219,6 +219,6 @@ using alias = T;
 // CHECK-USRS: index-templates.cpp c:@ST>2#T#T@Y Extent=[27:1 - 31:2]
 // CHECK-USRS: index-templates.cpp c:index-templates.cpp@443 Extent=[27:10 - 27:20]
 // CHECK-USRS: index-templates.cpp c:index-templates.cpp@455 Extent=[27:22 - 27:32]
-// CHECK-USRS-NOT: type
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@ST>2#T#T@Y@UUT@T::type Extent=[29:3 - 29:25]
 // CHECK-USRS: index-templates.cpp c:@S@Z3 Extent=[33:1 - 33:14]
 // CHECK-USRS: index-templates.cpp c:@F@f#$@S@map>#$@S@Z4#$@S@Pair>#I#S1_#$@S@compare>#$@S@Pair>#S1_#S2_#$@S@allocator>#S4_#
index a2ef68be49dec0d1553feafe56776c888a5785ec..ffe5c486dddae7b13eae270aef33d176d6660bed 100644 (file)
@@ -1258,6 +1258,7 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage
   case SymbolKind::Module:
   case SymbolKind::Macro:
   case SymbolKind::ClassProperty:
+  case SymbolKind::Using:
     return CXIdxEntity_Unexposed;
 
   case SymbolKind::Enum: return CXIdxEntity_Enum;