DiegoAstiazaran created this revision.
DiegoAstiazaran added reviewers: juliehockett, jakehehrlich, lebedev.ri.
DiegoAstiazaran added a project: clang-tools-extra.
Herald added subscribers: kadircet, arphaman.

In serialize::parseBases(...), when a base record is a template specialization, 
the specialization was used as the parent. It should be the base template so 
there is only one file generated for this record. When the specialized template 
is implicitly declared the reference USR corresponded to the GlobalNamespace's 
USR, this will now be the base template's USR.
More information about templates will be added later.

In serialize::emiInfo(RecorDecl*, ...), typedef records were not handled and 
the name was empty. This is now handled and a IsTypeDef attribute is added to 
RecordInfo struct.

In serialize::emitInfo(CXXMethodDecl*, ...), template specialization is handled 
like in serialize::parseBases(...).

Bitcode writer and reader are modified to handle the new attribute of 
RecordInfo.


https://reviews.llvm.org/D63367

Files:
  clang-tools-extra/clang-doc/BitcodeReader.cpp
  clang-tools-extra/clang-doc/BitcodeWriter.cpp
  clang-tools-extra/clang-doc/BitcodeWriter.h
  clang-tools-extra/clang-doc/Representation.h
  clang-tools-extra/clang-doc/Serialize.cpp
  clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
  clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -142,7 +142,15 @@
   E() {}
 protected:
   void ProtectedMethod();
-};)raw", 3, /*Public=*/false, Infos);
+};
+template <typename T>
+struct F {
+  void TemplateMethod();
+};
+template <>
+void F<int>::TemplateMethod();
+typedef struct {} G;)raw",
+                       7, /*Public=*/false, Infos);
 
   RecordInfo *E = InfoAsRecord(Infos[0].get());
   RecordInfo ExpectedE(EmptySID, "E");
@@ -176,6 +184,51 @@
   Method.IsMethod = true;
   ExpectedRecordWithMethod.ChildFunctions.emplace_back(std::move(Method));
   CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
+
+  RecordInfo *F = InfoAsRecord(Infos[3].get());
+  RecordInfo ExpectedF(EmptySID, "F");
+  ExpectedF.TagType = TagTypeKind::TTK_Struct;
+  ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  CheckRecordInfo(&ExpectedF, F);
+
+  RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[4].get());
+  RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
+  FunctionInfo TemplateMethod;
+  TemplateMethod.Name = "TemplateMethod";
+  TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
+  TemplateMethod.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
+  TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
+  TemplateMethod.Access = AccessSpecifier::AS_public;
+  TemplateMethod.IsMethod = true;
+  ExpectedRecordWithTemplateMethod.ChildFunctions.emplace_back(
+      std::move(TemplateMethod));
+  CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
+
+  RecordInfo *TemplatedRecord = InfoAsRecord(Infos[5].get());
+  RecordInfo ExpectedTemplatedRecord(EmptySID);
+  FunctionInfo SpecializedTemplateMethod;
+  SpecializedTemplateMethod.Name = "TemplateMethod";
+  SpecializedTemplateMethod.Parent =
+      Reference(EmptySID, "F", InfoType::IT_record);
+  SpecializedTemplateMethod.ReturnType =
+      TypeInfo(EmptySID, "void", InfoType::IT_default);
+  SpecializedTemplateMethod.Loc.emplace_back(0,
+                                             llvm::SmallString<16>{"test.cpp"});
+  SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
+                                                   InfoType::IT_record);
+  SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
+  SpecializedTemplateMethod.IsMethod = true;
+  ExpectedTemplatedRecord.ChildFunctions.emplace_back(
+      std::move(SpecializedTemplateMethod));
+  CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
+
+  RecordInfo *G = InfoAsRecord(Infos[6].get());
+  RecordInfo ExpectedG(EmptySID, "G");
+  ExpectedG.TagType = TagTypeKind::TTK_Struct;
+  ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedG.IsTypeDef = true;
+  CheckRecordInfo(&ExpectedG, G);
 }
 
 // Test serialization of enum declarations.
@@ -284,9 +337,13 @@
 
 TEST(SerializeTest, emitInheritedRecordInfo) {
   EmittedInfoList Infos;
-  ExtractInfosFromCode(
-      "class F {}; class G{} ; class E : public F, virtual private G {};", 3,
-      /*Public=*/false, Infos);
+  ExtractInfosFromCode(R"raw(class F {};
+class G {} ;
+class E : public F, virtual private G {};
+template <typename T>
+class H {} ;
+class I : public H<int> {} ;)raw",
+                       5, /*Public=*/false, Infos);
 
   RecordInfo *F = InfoAsRecord(Infos[0].get());
   RecordInfo ExpectedF(EmptySID, "F");
@@ -307,6 +364,19 @@
   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   ExpectedE.TagType = TagTypeKind::TTK_Class;
   CheckRecordInfo(&ExpectedE, E);
+
+  RecordInfo *H = InfoAsRecord(Infos[3].get());
+  RecordInfo ExpectedH(EmptySID, "H");
+  ExpectedH.TagType = TagTypeKind::TTK_Class;
+  ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  CheckRecordInfo(&ExpectedH, H);
+
+  RecordInfo *I = InfoAsRecord(Infos[4].get());
+  RecordInfo ExpectedI(EmptySID, "I");
+  ExpectedI.Parents.emplace_back(EmptySID, "H<int>", InfoType::IT_record);
+  ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedI.TagType = TagTypeKind::TTK_Class;
+  CheckRecordInfo(&ExpectedI, I);
 }
 
 TEST(SerializeTest, emitModulePublicLFunctions) {
Index: clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
+++ clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
@@ -151,6 +151,8 @@
 
   EXPECT_EQ(Expected->TagType, Actual->TagType);
 
+  EXPECT_EQ(Expected->IsTypeDef, Actual->IsTypeDef);
+
   ASSERT_EQ(Expected->Members.size(), Actual->Members.size());
   for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx)
     EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]);
Index: clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
+++ clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
@@ -80,6 +80,7 @@
 
   I.Members.emplace_back("int", "X", AccessSpecifier::AS_private);
   I.TagType = TagTypeKind::TTK_Class;
+  I.IsTypeDef = true;
   I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
 
Index: clang-tools-extra/clang-doc/Serialize.cpp
===================================================================
--- clang-tools-extra/clang-doc/Serialize.cpp
+++ clang-tools-extra/clang-doc/Serialize.cpp
@@ -179,10 +179,9 @@
 }
 
 static RecordDecl *getDeclForType(const QualType &T) {
-  auto *Ty = T->getAs<RecordType>();
-  if (!Ty)
-    return nullptr;
-  return Ty->getDecl()->getDefinition();
+  if (const auto *D = T->getAsRecordDecl())
+    return D->getDefinition();
+  return nullptr;
 }
 
 static bool isPublic(const clang::AccessSpecifier AS,
@@ -249,10 +248,14 @@
   for (const CXXBaseSpecifier &B : D->bases()) {
     if (B.isVirtual())
       continue;
-    if (const auto *P = getDeclForType(B.getType()))
+    if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
+      const auto *D = Ty->getTemplateName().getAsTemplateDecl();
+      I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
+                             InfoType::IT_record);
+    } else if (const auto *P = getDeclForType(B.getType()))
       I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                              InfoType::IT_record);
-    else
+    else 
       I.Parents.emplace_back(B.getType().getAsString());
   }
   for (const CXXBaseSpecifier &B : D->vbases()) {
@@ -343,8 +346,13 @@
   populateSymbolInfo(*I, D, FC, LineNumber, File);
   I->TagType = D->getTagKind();
   parseFields(*I, D, PublicOnly);
-  if (const auto *C = dyn_cast<CXXRecordDecl>(D))
+  if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
+    if (const auto *TD = C->getTypedefNameForAnonDecl()) {
+      I->Name = TD->getNameAsString();
+      I->IsTypeDef = true;
+    }
     parseBases(*I, C);
+  }
   return std::unique_ptr<Info>{std::move(I)};
 }
 
@@ -376,9 +384,16 @@
   populateFunctionInfo(Func, D, FC, LineNumber, File);
   Func.IsMethod = true;
 
-  SymbolID ParentUSR = getUSRForDecl(D->getParent());
-  Func.Parent = Reference{ParentUSR, D->getParent()->getNameAsString(),
-                          InfoType::IT_record};
+  const NamedDecl *Parent;
+  if (const auto *SD =
+          dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
+    Parent = SD->getSpecializedTemplate();
+  else
+    Parent = D->getParent();
+
+  SymbolID ParentUSR = getUSRForDecl(Parent);
+  Func.Parent =
+      Reference{ParentUSR, Parent->getNameAsString(), InfoType::IT_record};
   Func.Access = D->getAccess();
 
   // Wrap in enclosing scope
Index: clang-tools-extra/clang-doc/Representation.h
===================================================================
--- clang-tools-extra/clang-doc/Representation.h
+++ clang-tools-extra/clang-doc/Representation.h
@@ -241,6 +241,7 @@
   TagTypeKind TagType = TagTypeKind::TTK_Struct; // Type of this record
                                                  // (struct, class, union,
                                                  // interface).
+  bool IsTypeDef = false; // Indicates if record was declared using typedef
   llvm::SmallVector<MemberTypeInfo, 4>
       Members;                             // List of info about record members.
   llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
Index: clang-tools-extra/clang-doc/BitcodeWriter.h
===================================================================
--- clang-tools-extra/clang-doc/BitcodeWriter.h
+++ clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -102,6 +102,7 @@
   RECORD_DEFLOCATION,
   RECORD_LOCATION,
   RECORD_TAG_TYPE,
+  RECORD_IS_TYPE_DEF,
   REFERENCE_USR,
   REFERENCE_NAME,
   REFERENCE_TYPE,
Index: clang-tools-extra/clang-doc/BitcodeWriter.cpp
===================================================================
--- clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -159,6 +159,7 @@
           {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
           {RECORD_LOCATION, {"Location", &LocationAbbrev}},
           {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
+          {RECORD_IS_TYPE_DEF, {"IsTypeDef", &BoolAbbrev}},
           {FUNCTION_USR, {"USR", &SymbolIDAbbrev}},
           {FUNCTION_NAME, {"Name", &StringAbbrev}},
           {FUNCTION_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
@@ -202,7 +203,7 @@
         // Record Block
         {BI_RECORD_BLOCK_ID,
          {RECORD_USR, RECORD_NAME, RECORD_DEFLOCATION, RECORD_LOCATION,
-          RECORD_TAG_TYPE}},
+          RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
         // Function Block
         {BI_FUNCTION_BLOCK_ID,
          {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
@@ -471,6 +472,7 @@
   for (const auto &L : I.Loc)
     emitRecord(L, RECORD_LOCATION);
   emitRecord(I.TagType, RECORD_TAG_TYPE);
+  emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
   for (const auto &N : I.Members)
     emitBlock(N);
   for (const auto &P : I.Parents)
Index: clang-tools-extra/clang-doc/BitcodeReader.cpp
===================================================================
--- clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -167,6 +167,8 @@
     return decodeRecord(R, I->Loc, Blob);
   case RECORD_TAG_TYPE:
     return decodeRecord(R, I->TagType, Blob);
+  case RECORD_IS_TYPE_DEF:
+    return decodeRecord(R, I->IsTypeDef, Blob);
   default:
     return llvm::make_error<llvm::StringError>(
         "Invalid field for RecordInfo.\n", llvm::inconvertibleErrorCode());
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to