martong updated this revision to Diff 249350.
martong marked an inline comment as done.
martong added a comment.
- Handle AttributedTypeLoc
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,318 @@
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);
+ llvm_unreachable("Unimplemented TypeLoc visitor function");
+ }
+
+ Error VisitQualifiedTypeLoc(QualifiedTypeLoc From) {
+ auto To = ToL.castAs<QualifiedTypeLoc>();
+ // Import the unqualified TypeLoc.
+ return TypeLocImporter(Importer, To.getNextTypeLoc())
+ .Visit(From.getNextTypeLoc());
+ }
+
+ Error VisitAttributedTypeLoc(AttributedTypeLoc From) {
+ auto To = ToL.castAs<AttributedTypeLoc>();
+ return TypeLocImporter(Importer, To.getModifiedLoc())
+ .Visit(From.getModifiedLoc());
+ }
+
+ 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits