[clang-tools-extra] r364222 - [clang-doc] Add basic support for templates and typedef

Julie Hockett via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 24 12:31:03 PDT 2019


Author: juliehockett
Date: Mon Jun 24 12:31:02 2019
New Revision: 364222

URL: http://llvm.org/viewvc/llvm-project?rev=364222&view=rev
Log:
[clang-doc] Add basic support for templates and typedef

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.

Submitted on behalf of Diego Astiazarán (diegoaat97 at gmail.com)
Differential Revision: https://reviews.llvm.org/D63367

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

Modified: clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp Mon Jun 24 12:31:02 2019
@@ -167,6 +167,8 @@ llvm::Error parseRecord(Record R, unsign
     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());

Modified: clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp Mon Jun 24 12:31:02 2019
@@ -159,6 +159,7 @@ static const llvm::IndexedMap<RecordIdDs
           {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 @@ static const std::vector<std::pair<Block
         // 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 @@ void ClangDocBitcodeWriter::emitBlock(co
   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)

Modified: clang-tools-extra/trunk/clang-doc/BitcodeWriter.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeWriter.h?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/BitcodeWriter.h (original)
+++ clang-tools-extra/trunk/clang-doc/BitcodeWriter.h Mon Jun 24 12:31:02 2019
@@ -102,6 +102,7 @@ enum RecordId {
   RECORD_DEFLOCATION,
   RECORD_LOCATION,
   RECORD_TAG_TYPE,
+  RECORD_IS_TYPE_DEF,
   REFERENCE_USR,
   REFERENCE_NAME,
   REFERENCE_TYPE,

Modified: clang-tools-extra/trunk/clang-doc/Representation.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.h?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Representation.h (original)
+++ clang-tools-extra/trunk/clang-doc/Representation.h Mon Jun 24 12:31:02 2019
@@ -241,6 +241,7 @@ struct RecordInfo : public SymbolInfo {
   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

Modified: clang-tools-extra/trunk/clang-doc/Serialize.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Serialize.cpp?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Serialize.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/Serialize.cpp Mon Jun 24 12:31:02 2019
@@ -179,10 +179,9 @@ static SymbolID getUSRForDecl(const Decl
 }
 
 static RecordDecl *getDeclForType(const QualType &T) {
-  auto *Ty = T->getAs<RecordType>();
-  if (!Ty)
-    return nullptr;
-  return Ty->getDecl()->getDefinition();
+  if (const RecordDecl *D = T->getAsRecordDecl())
+    return D->getDefinition();
+  return nullptr;
 }
 
 static bool isPublic(const clang::AccessSpecifier AS,
@@ -249,7 +248,11 @@ static void parseBases(RecordInfo &I, co
   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 TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
+      I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
+                             InfoType::IT_record);
+    } else if (const RecordDecl *P = getDeclForType(B.getType()))
       I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                              InfoType::IT_record);
     else
@@ -343,8 +346,13 @@ std::unique_ptr<Info> emitInfo(const Rec
   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 TypedefNameDecl *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 @@ std::unique_ptr<Info> emitInfo(const CXX
   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 = nullptr;
+  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

Modified: clang-tools-extra/trunk/unittests/clang-doc/BitcodeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/BitcodeTest.cpp?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/BitcodeTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/BitcodeTest.cpp Mon Jun 24 12:31:02 2019
@@ -80,6 +80,7 @@ TEST(BitcodeTest, emitRecordInfoBitcode)
 
   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);
 

Modified: clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp Mon Jun 24 12:31:02 2019
@@ -151,6 +151,8 @@ void CheckRecordInfo(RecordInfo *Expecte
 
   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]);

Modified: clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp?rev=364222&r1=364221&r2=364222&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp Mon Jun 24 12:31:02 2019
@@ -142,7 +142,15 @@ public:
   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 @@ protected:
   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, emitInlinedFunctionI
 
 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 @@ TEST(SerializeTest, emitInheritedRecordI
   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) {




More information about the cfe-commits mailing list