martong updated this revision to Diff 250570.
martong added a comment.

- Fix the base commit of this patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71018/new/

https://reviews.llvm.org/D71018

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -5845,6 +5845,53 @@
   EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
 }
 
+struct ImportTypeLoc : ASTImporterOptionSpecificTestBase {};
+
+TEST_P(ImportTypeLoc, Function) {
+  Decl *FromTU = getTuDecl(
+      R"(
+      int f(int p) {
+        return 1;
+      }
+      )",
+      Lang_CXX11, "input0.cc");
+  FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("f")));
+  FunctionDecl *ToF = Import(FromF, Lang_CXX11);
+  ASSERT_TRUE(ToF);
+  FunctionProtoTypeLoc TL =
+      ToF->getTypeSourceInfo()->getTypeLoc().castAs<FunctionProtoTypeLoc>();
+  EXPECT_EQ(TL.getNumParams(), 1u);
+  EXPECT_TRUE(TL.getParam(0));
+}
+
+TEST_P(ImportTypeLoc, Lambda) {
+  // In this test case, first the CXXRecordDecl of the lambda is imported, then
+  // the operator().
+  Decl *FromTU = getTuDecl(
+      R"(
+      auto l1 = [](unsigned lp) { return 1; };
+      int f(int p) {
+        return l1(p);
+      }
+      )",
+      Lang_CXX11, "input0.cc");
+  FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("f")));
+  FunctionDecl *ToF = Import(FromF, Lang_CXX11);
+  ASSERT_TRUE(ToF);
+
+  TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+  CXXMethodDecl *ToLambdaMD = FirstDeclMatcher<LambdaExpr>()
+                                  .match(ToTU, lambdaExpr())
+                                  ->getCallOperator();
+  FunctionProtoTypeLoc TL = ToLambdaMD->getTypeSourceInfo()
+                                ->getTypeLoc()
+                                .castAs<FunctionProtoTypeLoc>();
+  EXPECT_EQ(TL.getNumParams(), 1u);
+  EXPECT_TRUE(TL.getParam(0));
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
                         DefaultTestValuesForRunOptions, );
 
@@ -5903,5 +5950,8 @@
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
                         DefaultTestValuesForRunOptions, );
 
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportTypeLoc,
+                        DefaultTestValuesForRunOptions, );
+
 } // end namespace ast_matchers
 } // end namespace clang
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -42,6 +42,7 @@
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeLocVisitor.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/Builtins.h"
@@ -695,6 +696,8 @@
     // that type is declared inside the body of the function.
     // E.g. auto f() { struct X{}; return X(); }
     bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
+
+    friend class TypeLocImporter;
   };
 
 template <typename InContainerTy>
@@ -3275,6 +3278,15 @@
         FromReturnTy, FromFPT->getParamTypes(), FromEPI);
   }
 
+  // Import the function parameters.
+  SmallVector<ParmVarDecl *, 8> Parameters;
+  for (auto P : D->parameters()) {
+    if (Expected<ParmVarDecl *> ToPOrErr = import(P))
+      Parameters.push_back(*ToPOrErr);
+    else
+      return ToPOrErr.takeError();
+  }
+
   QualType T;
   TypeSourceInfo *TInfo;
   SourceLocation ToInnerLocStart, ToEndLoc;
@@ -3288,15 +3300,6 @@
   else
     return Imp.takeError();
 
-  // Import the function parameters.
-  SmallVector<ParmVarDecl *, 8> Parameters;
-  for (auto P : D->parameters()) {
-    if (Expected<ParmVarDecl *> ToPOrErr = import(P))
-      Parameters.push_back(*ToPOrErr);
-    else
-      return ToPOrErr.takeError();
-  }
-
   // Create the imported function.
   FunctionDecl *ToFunction = nullptr;
   if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
@@ -3402,16 +3405,6 @@
   }
   ToFunction->setParams(Parameters);
 
-  // We need to complete creation of FunctionProtoTypeLoc manually with setting
-  // params it refers to.
-  if (TInfo) {
-    if (auto ProtoLoc =
-        TInfo->getTypeLoc().IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
-      for (unsigned I = 0, N = Parameters.size(); I != N; ++I)
-        ProtoLoc.setParam(I, Parameters[I]);
-    }
-  }
-
   // Import the describing template function, if any.
   if (FromFT) {
     auto ToFTOrErr = import(FromFT);
@@ -8111,20 +8104,305 @@
   return ToContext.getQualifiedType(*ToTOrErr, FromT.getLocalQualifiers());
 }
 
+namespace clang {
+
+#define IMPORT_TYPE_LOC_OR_RETURN_ERROR(NAME)                                  \
+  if (auto ImpOrErr = Importer.Import(From.get##NAME()))                       \
+    To.set##NAME(*ImpOrErr);                                                   \
+  else                                                                         \
+    return ImpOrErr.takeError();
+
+// Import TypeLoc information.
+// TypeLocReader in ASTReader.cpp gives hints about what to import.
+// (At some ObjC types not every existing location is copied.)
+class TypeLocImporter : public TypeLocVisitor<TypeLocImporter, Error> {
+  ASTImporter &Importer;
+  TypeLoc ToL;
+
+public:
+  TypeLocImporter(ASTImporter &Importer, TypeLoc ToL)
+      : Importer(Importer), ToL(ToL) {}
+
+  Error VisitTypeLoc(TypeLoc From) {
+    // The visitor does not call directly VisitTypeSpecTypeLoc, because that is
+    // not a leaf node in the hierarchy (i.e. there is no such enum value in
+    // TypeNodes.inc).
+    if (auto FTS = From.getAs<TypeSpecTypeLoc>())
+      return VisitTypeSpecTypeLoc(FTS);
+    return Error::success();
+  }
+
+  Error VisitTypeSpecTypeLoc(TypeSpecTypeLoc From) {
+    auto To = ToL.castAs<TypeSpecTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(NameLoc);
+    return Error::success();
+  }
+
+  Error VisitBuiltinTypeLoc(BuiltinTypeLoc From) {
+    auto To = ToL.castAs<BuiltinTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(BuiltinLoc);
+    return Error::success();
+  }
+
+  Error VisitParenTypeLoc(ParenTypeLoc From) {
+    auto To = ToL.castAs<ParenTypeLoc>();
+
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LParenLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RParenLoc);
+
+    return Error::success();
+  }
+
+  Error VisitPointerTypeLoc(PointerTypeLoc From) {
+    auto To = ToL.castAs<PointerTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(StarLoc);
+    return Error::success();
+  }
+
+  Error VisitBlockPointerTypeLoc(BlockPointerTypeLoc From) {
+    auto To = ToL.castAs<BlockPointerTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(CaretLoc);
+    return Error::success();
+  }
+
+  Error VisitMemberPointerTypeLoc(MemberPointerTypeLoc From) {
+    auto To = ToL.castAs<MemberPointerTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(StarLoc);
+    return Error::success();
+  }
+
+  Error VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc From) {
+    auto To = ToL.castAs<ObjCObjectPointerTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(StarLoc);
+    return Error::success();
+  }
+
+  Error VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc From) {
+    auto To = ToL.castAs<LValueReferenceTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(AmpLoc);
+    return Error::success();
+  }
+
+  Error VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc From) {
+    auto To = ToL.castAs<RValueReferenceTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(AmpAmpLoc);
+    return Error::success();
+  }
+
+  Error VisitFunctionTypeLoc(FunctionTypeLoc From) {
+    auto To = ToL.castAs<FunctionTypeLoc>();
+
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LocalRangeBegin);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LocalRangeEnd);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LParenLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RParenLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(ExceptionSpecRange);
+
+    for (unsigned I = 0; I < From.getNumParams(); ++I)
+      To.setParam(
+          I, cast_or_null<ParmVarDecl>(
+                 // In the case of importing a lambda CXXRecordDecl the
+                 // parameter had not been imported yet. That will be imported
+                 // later when the lambda's operator() is imported.
+                 Importer.GetAlreadyImportedOrNull(From.getParam(I))));
+
+    return Error::success();
+  }
+
+  Error VisitArrayTypeLoc(ArrayTypeLoc From) {
+    auto To = ToL.castAs<ArrayTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LBracketLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RBracketLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(SizeExpr);
+    return Error::success();
+  }
+
+  Error VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc From) {
+    auto To = ToL.castAs<TemplateSpecializationTypeLoc>();
+
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TemplateKeywordLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LAngleLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RAngleLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TemplateNameLoc);
+
+    ASTNodeImporter NodeImporter(Importer);
+    for (unsigned I = 0; I < From.getNumArgs(); ++I) {
+      if (Expected<TemplateArgumentLoc> TAL =
+              NodeImporter.import(From.getArgLoc(I)))
+        To.setArgLocInfo(I, TAL->getLocInfo());
+      else
+        return TAL.takeError();
+    }
+
+    return Error::success();
+  }
+
+  Error VisitDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc From) {
+    auto To = ToL.castAs<DependentAddressSpaceTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(AttrNameLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(AttrOperandParensRange);
+    // FIXME: Import other things?
+    return Error::success();
+  }
+
+  Error VisitTypeOfTypeLoc(TypeOfTypeLoc From) {
+    auto To = ToL.castAs<TypeOfTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(UnderlyingTInfo);
+    return Error::success();
+  }
+
+  Error VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc From) {
+    auto To = ToL.castAs<UnaryTransformTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(KWLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LParenLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RParenLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(UnderlyingTInfo);
+    return Error::success();
+  }
+
+  Error VisitDeducedTemplateSpecializationTypeLoc(
+      DeducedTemplateSpecializationTypeLoc From) {
+    auto To = ToL.castAs<DeducedTemplateSpecializationTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TemplateNameLoc);
+    return Error::success();
+  }
+
+  Error VisitElaboratedTypeLoc(ElaboratedTypeLoc From) {
+    auto To = ToL.castAs<ElaboratedTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(ElaboratedKeywordLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(QualifierLoc);
+    return Error::success();
+  }
+
+  Error VisitDependentNameTypeLoc(DependentNameTypeLoc From) {
+    auto To = ToL.castAs<DependentNameTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(ElaboratedKeywordLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(QualifierLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(NameLoc);
+    return Error::success();
+  }
+
+  Error VisitDependentTemplateSpecializationTypeLoc(
+      DependentTemplateSpecializationTypeLoc From) {
+    auto To = ToL.castAs<DependentTemplateSpecializationTypeLoc>();
+
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(ElaboratedKeywordLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(QualifierLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TemplateKeywordLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TemplateNameLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LAngleLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RAngleLoc);
+
+    ASTNodeImporter NodeImporter(Importer);
+    for (unsigned I = 0; I < From.getNumArgs(); ++I) {
+      if (Expected<TemplateArgumentLoc> TAL =
+              NodeImporter.import(From.getArgLoc(I)))
+        To.setArgLocInfo(I, TAL->getLocInfo());
+      else
+        return TAL.takeError();
+    }
+
+    return Error::success();
+  }
+
+  Error VisitPackExpansionTypeLoc(PackExpansionTypeLoc From) {
+    auto To = ToL.castAs<PackExpansionTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(EllipsisLoc);
+    return Error::success();
+  }
+
+  Error VisitAtomicTypeLoc(AtomicTypeLoc From) {
+    auto To = ToL.castAs<AtomicTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(KWLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(LParenLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(RParenLoc);
+    return Error::success();
+  }
+
+  Error VisitPipeTypeLoc(PipeTypeLoc From) {
+    auto To = ToL.castAs<PipeTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(KWLoc);
+    return Error::success();
+  }
+
+  Error VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc From) {
+    auto To = ToL.castAs<ObjCTypeParamTypeLoc>();
+    if (From.getNumProtocols()) {
+      IMPORT_TYPE_LOC_OR_RETURN_ERROR(ProtocolLAngleLoc);
+      IMPORT_TYPE_LOC_OR_RETURN_ERROR(ProtocolRAngleLoc);
+      for (unsigned I = 0; I < From.getNumProtocols(); ++I) {
+        if (ExpectedSLoc L = Importer.Import(From.getProtocolLoc(I)))
+          To.setProtocolLoc(I, *L);
+        else
+          return L.takeError();
+      }
+    }
+    return Error::success();
+  }
+
+  Error VisitObjCObjectTypeLoc(ObjCObjectTypeLoc From) {
+    auto To = ToL.castAs<ObjCObjectTypeLoc>();
+
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TypeArgsLAngleLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(TypeArgsRAngleLoc);
+
+    for (unsigned I = 0; I < From.getNumTypeArgs(); ++I) {
+      if (Expected<TypeSourceInfo *> TSI =
+              Importer.Import(From.getTypeArgTInfo(I)))
+        To.setTypeArgTInfo(I, *TSI);
+      else
+        return TSI.takeError();
+    }
+
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(ProtocolLAngleLoc);
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(ProtocolRAngleLoc);
+
+    for (unsigned I = 0; I < From.getNumProtocols(); ++I) {
+      if (ExpectedSLoc L = Importer.Import(From.getProtocolLoc(I)))
+        To.setProtocolLoc(I, *L);
+      else
+        return L.takeError();
+    }
+
+    To.setHasBaseTypeAsWritten(From.hasBaseTypeAsWritten());
+
+    return Error::success();
+  }
+
+  Error VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc From) {
+    auto To = ToL.castAs<ObjCInterfaceTypeLoc>();
+    IMPORT_TYPE_LOC_OR_RETURN_ERROR(NameLoc);
+    return Error::success();
+  }
+
+};
+
+#undef IMPORT_TYPE_LOC_OR_RETURN_ERROR
+
+} // namespace clang
+
 Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) {
   if (!FromTSI)
     return FromTSI;
 
-  // FIXME: For now we just create a "trivial" type source info based
-  // on the type and a single location. Implement a real version of this.
   ExpectedType TOrErr = Import(FromTSI->getType());
   if (!TOrErr)
     return TOrErr.takeError();
-  ExpectedSLoc BeginLocOrErr = Import(FromTSI->getTypeLoc().getBeginLoc());
-  if (!BeginLocOrErr)
-    return BeginLocOrErr.takeError();
 
-  return ToContext.getTrivialTypeSourceInfo(*TOrErr, *BeginLocOrErr);
+  TypeSourceInfo *ToTSI = ToContext.CreateTypeSourceInfo(*TOrErr);
+
+  TypeLoc FromL = FromTSI->getTypeLoc();
+  TypeLoc ToL = ToTSI->getTypeLoc();
+  while (FromL) {
+    assert(ToL && "Not consistent TypeSourceInfo");
+    TypeLocImporter Importer(*this, ToL);
+    if (Error Err = Importer.Visit(FromL))
+      return std::move(Err);
+    FromL = FromL.getNextTypeLoc();
+    ToL = ToL.getNextTypeLoc();
+  }
+
+  return ToTSI;
 }
 
 Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to