khazem created this revision. khazem added reviewers: spyffe, sepavloff. khazem added subscribers: phosek, khazem, NoQ, xazax.hun, cfe-commits.
This patch implements some expression-related AST node import (patch #2). - Some code cleanup - Add tests not present in http://reviews.llvm.org/D14286 - Integrate a test suite from Serge Pavlov (http://reviews.llvm.org/D14224) - Implement import of some nodes: ArrayTypeTraitExpr ExpressionTraitExpr OpaqueValueExpr ArraySubscriptExpr ExplicitCastExpr ImplicitValueInitExpr OffsetOfExpr CXXThisExpr CXXThrowExpr CXXNoexceptExpr CXXDefaultArgExpr CXXScalarValueInitExpr CXXBindTemporaryExpr CXXTemporaryObjectExpr MaterializeTemporaryExpr ExprWithCleanups StaticAssertDecl FriendDecl DecayedType https://reviews.llvm.org/D24878 Files: include/clang/AST/ASTImporter.h include/clang/AST/DeclFriend.h lib/AST/ASTImporter.cpp test/ASTMerge/Inputs/class3.cpp test/ASTMerge/Inputs/exprs3.cpp test/ASTMerge/class2.cpp test/ASTMerge/exprs.cpp unittests/AST/ASTImporterTest.cpp
Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -456,5 +456,24 @@ } +const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr; + +TEST(ImportExpr, ImportVAArgExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport(__builtin_va_list list, ...) {" + " (void)__builtin_va_arg(list, int); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + cStyleCastExpr( + hasSourceExpression( + vaArgExpr())))))))); +} + + } // end namespace ast_matchers } // end namespace clang Index: test/ASTMerge/exprs.cpp =================================================================== --- /dev/null +++ test/ASTMerge/exprs.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/exprs3.cpp +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s +// expected-no-diagnostics + +static_assert(Ch1 == 'a'); +static_assert(Ch2 == 'b'); +static_assert(Ch3 == 'c'); + +static_assert(Ch4 == L'd'); +static_assert(Ch5 == L'e'); +static_assert(Ch6 == L'f'); + +static_assert(C1 == 12); +static_assert(C2 == 13); + +static_assert(C3 == 12); +static_assert(C4 == 13); + +static_assert(C5 == 22L); +static_assert(C6 == 23L); + +static_assert(C7 == 66LL); +static_assert(C8 == 67ULL); + +static_assert(bval1 == true); +static_assert(bval2 == false); + +static_assert(ExpressionTrait == false); + +static_assert(ArrayRank == 2); +static_assert(ArrayExtent == 20); + +void testImport(int *x, const S1 &cs1, S1 &s1) { + testNewThrowDelete(); + testArrayElement(nullptr, 12); + testTernaryOp(0, 1, 2); + testConstCast(cs1); + testStaticCast(s1); + testReinterpretCast(s1); + testDynamicCast(s1); + testScalarInit(42); + testOffsetOf(); + testDefaultArg(12); + useTemplateType(); +} Index: test/ASTMerge/class2.cpp =================================================================== --- /dev/null +++ test/ASTMerge/class2.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/class3.cpp +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s +// expected-no-diagnostics + +class C3 { + int method_1(C2 *x) { + return x->x; + } +}; Index: test/ASTMerge/Inputs/exprs3.cpp =================================================================== --- /dev/null +++ test/ASTMerge/Inputs/exprs3.cpp @@ -0,0 +1,131 @@ +// Integer literals +const char Ch1 = 'a'; +const signed char Ch2 = 'b'; +const unsigned char Ch3 = 'c'; + +const wchar_t Ch4 = L'd'; +const signed wchar_t Ch5 = L'e'; +const unsigned wchar_t Ch6 = L'f'; + +const short C1 = 12; +const unsigned short C2 = 13; + +const int C3 = 12; +const unsigned int C4 = 13; + +const long C5 = 22; +const unsigned long C6 = 23; + +const long long C7 = 66; +const unsigned long long C8 = 67; + + +// String literals +const char str1[] = "ABCD"; +const char str2[] = "ABCD" "0123"; + +const wchar_t wstr1[] = L"DEF"; +const wchar_t wstr2[] = L"DEF" L"123"; + + +// Boolean literals +const bool bval1 = true; +const bool bval2 = false; + +// Floating Literals +const float F1 = 12.2F; +const double F2 = 1E4; +const long double F3 = 1.2E-3L; + + +// nullptr literal +const void *vptr = nullptr; + + +int glb_1[4] = { 10, 20, 30, 40 }; + +struct S1 { + int a; + int b[3]; +}; + +struct S2 { + int c; + S1 d; +}; + +S2 glb_2 = { 22, .d.a = 44, .d.b[0] = 55, .d.b[1] = 66 }; + +void testNewThrowDelete() { + throw; + char *p = new char[10]; + delete[] p; +} + +int testArrayElement(int *x, int n) { + return x[n]; +} + +int testTernaryOp(int c, int x, int y) { + return c ? x : y; +} + +S1 &testConstCast(const S1 &x) { + return const_cast<S1&>(x); +} + +S1 &testStaticCast(S1 &x) { + return static_cast<S1&>(x); +} + +S1 &testReinterpretCast(S1 &x) { + return reinterpret_cast<S1&>(x); +} + +S1 &testDynamicCast(S1 &x) { + return dynamic_cast<S1&>(x); +} + +int testScalarInit(int x) { + return int(x); +} + +struct S { + float f; + double d; +}; +struct T { + int i; + struct S s[10]; +}; + +void testOffsetOf() { + (void)__builtin_offsetof(struct T, s[2].d); +} + + +unsigned char asmFunc(unsigned char a, unsigned char b) { + unsigned int la = a; + unsigned int lb = b; + unsigned int bigres; + unsigned char res; + __asm__ ("0:\n1:\n" : [bigres] "=la"(bigres) : [la] "0"(la), [lb] "c"(lb) : + "edx", "cc"); + res = bigres; + return res; +} + +int testDefaultArg(int a = 2*2) { + return a; +} + +template <typename T> // T has TemplateTypeParmType +void testTemplateTypeParmType(int i); + +void useTemplateType() { + testTemplateTypeParmType<char>(4); +} + +const bool ExpressionTrait = __is_lvalue_expr(1); +const unsigned ArrayRank = __array_rank(int[10][20]); +const unsigned ArrayExtent = __array_extent(int[10][20], 1); Index: test/ASTMerge/Inputs/class3.cpp =================================================================== --- /dev/null +++ test/ASTMerge/Inputs/class3.cpp @@ -0,0 +1,26 @@ +class C1 { +public: + C1(); + ~C1(); + C1 *method_1() { + return this; + } + C1 method_2() { + return C1(); + } + void method_3() { + const C1 &ref = C1(); + } +}; + +class C11 : public C1 { +}; + +class C2 { +private: + int x; + friend class C3; +public: + static_assert(sizeof(x) == sizeof(int), "Error"); + typedef class C2::C2 InjType; +}; Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -40,6 +40,7 @@ // Importing types QualType VisitType(const Type *T); QualType VisitBuiltinType(const BuiltinType *T); + QualType VisitDecayedType(const DecayedType *T); QualType VisitComplexType(const ComplexType *T); QualType VisitPointerType(const PointerType *T); QualType VisitBlockPointerType(const BlockPointerType *T); @@ -88,6 +89,8 @@ DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + bool ImportCastPath(CastExpr *E, CXXCastPath &Path); + typedef DesignatedInitExpr::Designator Designator; Designator ImportDesignator(const Designator &D); @@ -123,6 +126,8 @@ TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); + TemplateArgumentLoc ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc, bool &Error); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs); @@ -136,6 +141,7 @@ bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); + Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); @@ -152,6 +158,7 @@ Decl *VisitCXXConversionDecl(CXXConversionDecl *D); Decl *VisitFieldDecl(FieldDecl *D); Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); + Decl *VisitFriendDecl(FriendDecl *D); Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -242,11 +249,25 @@ Expr *VisitConditionalOperator(ConditionalOperator *E); Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E); Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E); + Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); + Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E); + Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E); Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); - Expr *VisitCStyleCastExpr(CStyleCastExpr *E); + Expr *VisitExplicitCastExpr(ExplicitCastExpr *E); + Expr *VisitOffsetOfExpr(OffsetOfExpr *OE); + Expr *VisitCXXThrowExpr(CXXThrowExpr *E); + Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E); + Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); + Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); + Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); + Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE); + Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); + Expr *VisitCXXNewExpr(CXXNewExpr *CE); + Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); Expr *VisitMemberExpr(MemberExpr *E); @@ -272,13 +293,26 @@ bool Failed = false; std::transform(Ibegin, Iend, Obegin, [&ImporterRef, &Failed](ItemT *From) -> ItemT * { - ItemT *To = ImporterRef.Import(From); + ItemT *To = cast_or_null<ItemT>( + ImporterRef.Import(From)); if (!To && From) Failed = true; return To; }); return Failed; } + + template<typename InContainerTy, typename OutContainerTy> + bool ImportContainerChecked(const InContainerTy &InContainer, + OutContainerTy &OutContainer) { + return ImportArrayChecked(InContainer.begin(), InContainer.end(), + OutContainer.begin()); + } + + template<typename InContainerTy, typename OIter> + bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { + return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); + } }; } @@ -1611,6 +1645,14 @@ llvm_unreachable("Invalid BuiltinType Kind!"); } +QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { + QualType OrigT = Importer.Import(T->getOriginalType()); + if (OrigT.isNull()) + return QualType(); + + return Importer.getToContext().getDecayedType(OrigT); +} + QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) @@ -2267,18 +2309,10 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( TemplateParameterList *Params) { - SmallVector<NamedDecl *, 4> ToParams; - ToParams.reserve(Params->size()); - for (TemplateParameterList::iterator P = Params->begin(), - PEnd = Params->end(); - P != PEnd; ++P) { - Decl *To = Importer.Import(*P); - if (!To) - return nullptr; + SmallVector<NamedDecl *, 4> ToParams(Params->size()); + if (ImportContainerChecked(*Params, ToParams)) + return nullptr; - ToParams.push_back(cast<NamedDecl>(To)); - } - Expr *ToRequiresClause; if (Expr *const R = Params->getRequiresClause()) { ToRequiresClause = Importer.Import(R); @@ -2367,6 +2401,31 @@ llvm_unreachable("Invalid template argument kind"); } +TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc, bool &Error) { + Error = false; + TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); + TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); + TemplateArgumentLocInfo ToInfo; + if (Arg.getKind() == TemplateArgument::Expression) { + Expr *E = Importer.Import(FromInfo.getAsExpr()); + ToInfo = TemplateArgumentLocInfo(E); + if (!E) + Error = true; + } else if (Arg.getKind() == TemplateArgument::Type) { + if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) + ToInfo = TemplateArgumentLocInfo(TSI); + else + Error = true; + } else { + ToInfo = TemplateArgumentLocInfo( + Importer.Import(FromInfo.getTemplateQualifierLoc()), + Importer.Import(FromInfo.getTemplateNameLoc()), + Importer.Import(FromInfo.getTemplateEllipsisLoc())); + } + return TemplateArgumentLoc(Arg, ToInfo); +} + bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs) { @@ -2481,6 +2540,35 @@ return accessSpecDecl; } +Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + DeclContext *LexicalDC = DC; + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + Expr *AssertExpr = Importer.Import(D->getAssertExpr()); + if (!AssertExpr) + return nullptr; + + StringLiteral *FromMsg = D->getMessage(); + StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg)); + if (!ToMsg && FromMsg) + return nullptr; + + StaticAssertDecl *ToD = StaticAssertDecl::Create( + Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed()); + + ToD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToD); + Importer.Imported(D, ToD); + return ToD; +} + Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; @@ -3330,6 +3418,70 @@ return ToIndirectField; } +Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { + // Import the major distinguishing characteristics of a declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext() + ? DC : Importer.ImportContext(D->getLexicalDeclContext()); + if (!DC || !LexicalDC) + return nullptr; + + // Determine whether we've already imported this decl. + // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup. + CXXRecordDecl *RD = cast<CXXRecordDecl>(DC); + FriendDecl *ImportedFriend = RD->getFirstFriend(); + StructuralEquivalenceContext Context( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, false); + + while (ImportedFriend) { + if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { + if (Context.IsStructurallyEquivalent(D->getFriendDecl(), + ImportedFriend->getFriendDecl())) + return Importer.Imported(D, ImportedFriend); + + } else if (D->getFriendType() && ImportedFriend->getFriendType()) { + if (Importer.IsStructurallyEquivalent( + D->getFriendType()->getType(), + ImportedFriend->getFriendType()->getType(), true)) + return Importer.Imported(D, ImportedFriend); + } + ImportedFriend = ImportedFriend->getNextFriend(); + } + + // Not found. Create it. + FriendDecl::FriendUnion ToFU; + if (NamedDecl *FriendD = D->getFriendDecl()) + ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD)); + else + ToFU = Importer.Import(D->getFriendType()); + if (!ToFU) + return nullptr; + + SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); + TemplateParameterList **FromTPLists = + D->getTrailingObjects<TemplateParameterList *>(); + for (unsigned I = 0; I < D->NumTPLists; I++) { + TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]); + if (!List) + return nullptr; + ToTPLists[I] = List; + } + + FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + ToFU, Importer.Import(D->getFriendLoc()), + ToTPLists); + + Importer.Imported(D, FrD); + RD->pushFriendDecl(FrD); + + FrD->setAccess(D->getAccess()); + FrD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(FrD); + return FrD; +} + Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; @@ -4886,11 +5038,10 @@ } SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs()); - if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin())) + if (ImportContainerChecked(S->outputs(), Exprs)) return nullptr; - if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(), - Exprs.begin() + S->getNumOutputs())) + if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) return nullptr; StringLiteral *AsmStr = cast_or_null<StringLiteral>( @@ -4933,8 +5084,8 @@ Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { llvm::SmallVector<Stmt *, 8> ToStmts(S->size()); - - if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin())) + + if (ImportContainerChecked(S->body(), ToStmts)) return nullptr; SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); @@ -5388,7 +5539,7 @@ return nullptr; return new (Importer.getToContext()) GNUNullExpr( - T, Importer.Import(E->getExprLoc())); + T, Importer.Import(E->getLocStart())); } Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { @@ -5402,7 +5553,7 @@ return nullptr; return new (Importer.getToContext()) PredefinedExpr( - Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL); + Importer.Import(E->getLocStart()), T, E->getIdentType(), SL); } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { @@ -5421,6 +5572,23 @@ if (T.isNull()) return nullptr; + + TemplateArgumentListInfo ToTAInfo; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + const TemplateArgumentLoc *FromArgArray = E->getTemplateArgs(); + for (unsigned i = 0, e = E->getNumTemplateArgs(); i < e; i++) { + const TemplateArgumentLoc &FromLoc = FromArgArray[i]; + bool Error = false; + TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); + if (Error) + return nullptr; + else + ToTAInfo.addArgument(ToTALoc); + } + ResInfo = &ToTAInfo; + } + DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), Importer.Import(E->getQualifierLoc()), Importer.Import(E->getTemplateKeywordLoc()), @@ -5429,7 +5597,7 @@ Importer.Import(E->getLocation()), T, E->getValueKind(), FoundD, - /*FIXME:TemplateArgs=*/nullptr); + /*TemplateArgs=*/ResInfo); if (E->hadMultipleCandidates()) DRE->setHadMultipleCandidates(true); return DRE; @@ -5438,7 +5606,7 @@ Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return NULL; + return nullptr; return new (Importer.getToContext()) ImplicitValueInitExpr(T); } @@ -5607,8 +5775,7 @@ Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { SmallVector<Expr *, 4> Exprs(E->getNumExprs()); - if (ImportArrayChecked( - E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin())) + if (ImportContainerChecked(E->exprs(), Exprs)) return nullptr; return new (Importer.getToContext()) ParenListExpr( @@ -5746,6 +5913,38 @@ T, E->getValueKind(), E->getObjectKind()); } +Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo()); + if (!ToQueried) + return nullptr; + + Expr *Dim = Importer.Import(E->getDimensionExpression()); + if (!Dim && E->getDimensionExpression()) + return nullptr; + + return new (Importer.getToContext()) ArrayTypeTraitExpr( + Importer.Import(E->getLocStart()), E->getTrait(), ToQueried, + E->getValue(), Dim, Importer.Import(E->getLocEnd()), T); +} + +Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToQueried = Importer.Import(E->getQueriedExpression()); + if (!ToQueried) + return nullptr; + + return new (Importer.getToContext()) ExpressionTraitExpr( + Importer.Import(E->getLocStart()), E->getTrait(), ToQueried, + E->getValue(), Importer.Import(E->getLocEnd()), T); +} + Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5756,10 +5955,28 @@ return nullptr; return new (Importer.getToContext()) OpaqueValueExpr( - Importer.Import(E->getExprLoc()), T, E->getValueKind(), + Importer.Import(E->getLocation()), T, E->getValueKind(), E->getObjectKind(), SourceExpr); } +Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToLHS = Importer.Import(E->getLHS()); + if (!ToLHS) + return nullptr; + + Expr *ToRHS = Importer.Import(E->getRHS()); + if (!ToRHS) + return nullptr; + + return new (Importer.getToContext()) ArraySubscriptExpr( + ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(), + Importer.Import(E->getRBracketLoc())); +} + Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5790,11 +6007,14 @@ E->isFPContractable()); } -static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { - if (E->path_empty()) return false; - - // TODO: import cast paths - return true; +bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { + for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) { + if (CXXBaseSpecifier *Spec = Importer.Import(*I)) + Path.push_back(Spec); + else + return true; + } + return false; } Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { @@ -5814,7 +6034,7 @@ SubExpr, &BasePath, E->getValueKind()); } -Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { +Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) return nullptr; @@ -5831,11 +6051,320 @@ if (ImportCastPath(E, BasePath)) return nullptr; - return CStyleCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - Importer.Import(E->getLParenLoc()), - Importer.Import(E->getRParenLoc())); + switch (E->getStmtClass()) { + case Stmt::CStyleCastExprClass: { + CStyleCastExpr *CCE = cast<CStyleCastExpr>(E); + return CStyleCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + Importer.Import(CCE->getLParenLoc()), + Importer.Import(CCE->getRParenLoc())); + } + + case Stmt::CXXFunctionalCastExprClass: { + CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E); + return CXXFunctionalCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), TInfo, + E->getCastKind(), SubExpr, &BasePath, + Importer.Import(FCE->getLParenLoc()), + Importer.Import(FCE->getRParenLoc())); + } + + case Stmt::ObjCBridgedCastExprClass: { + ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E); + return new (Importer.getToContext()) ObjCBridgedCastExpr( + Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(), + E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()), + TInfo, SubExpr); + } + default: + break; // just fall through + } + + CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E); + SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()), + RParenLoc = Importer.Import(Named->getRParenLoc()); + SourceRange Brackets = Importer.Import(Named->getAngleBrackets()); + + switch (E->getStmtClass()) { + case Stmt::CXXStaticCastExprClass: + return CXXStaticCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXDynamicCastExprClass: + return CXXDynamicCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXReinterpretCastExprClass: + return CXXReinterpretCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), + SubExpr, &BasePath, TInfo, + ExprLoc, RParenLoc, Brackets); + + case Stmt::CXXConstCastExprClass: + return CXXConstCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), SubExpr, TInfo, ExprLoc, + RParenLoc, Brackets); + default: + llvm_unreachable("Cast expression of unsupported type!"); + return nullptr; + } +} + +Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) { + QualType T = Importer.Import(OE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<OffsetOfNode, 4> Nodes; + for (int I = 0, E = OE->getNumComponents(); I < E; ++I) { + const OffsetOfNode &Node = OE->getComponent(I); + + switch (Node.getKind()) { + case OffsetOfNode::Array: + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), + Node.getArrayExprIndex(), + Importer.Import(Node.getLocEnd()))); + break; + + case OffsetOfNode::Base: { + CXXBaseSpecifier *BS = Importer.Import(Node.getBase()); + if (!BS && Node.getBase()) + return nullptr; + Nodes.push_back(OffsetOfNode(BS)); + break; + } + case OffsetOfNode::Field: { + FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField())); + if (!FD) + return nullptr; + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD, + Importer.Import(Node.getLocEnd()))); + break; + } + case OffsetOfNode::Identifier: { + IdentifierInfo *ToII = Importer.Import(Node.getFieldName()); + if (!ToII) + return nullptr; + Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII, + Importer.Import(Node.getLocEnd()))); + break; + } + } + } + + SmallVector<Expr *, 4> Exprs(OE->getNumExpressions()); + for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) { + Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I)); + if (!ToIndexExpr) + return nullptr; + Exprs[I] = ToIndexExpr; + } + + TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo()); + if (!TInfo && OE->getTypeSourceInfo()) + return nullptr; + + return OffsetOfExpr::Create(Importer.getToContext(), T, + Importer.Import(OE->getOperatorLoc()), + TInfo, Nodes, Exprs, + Importer.Import(OE->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *Operand = Importer.Import(E->getOperand()); + if (!Operand) + return nullptr; + + CanThrowResult CanThrow; + if (E->isValueDependent()) + CanThrow = CT_Dependent; + else + CanThrow = E->getValue() ? CT_Can : CT_Cannot; + + return new (Importer.getToContext()) CXXNoexceptExpr( + T, Operand, CanThrow, + Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd())); +} + +Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr && E->getSubExpr()) + return nullptr; + + return new (Importer.getToContext()) CXXThrowExpr( + SubExpr, T, Importer.Import(E->getThrowLoc()), + E->isThrownVariableInScope()); +} + +Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + ParmVarDecl *Param = cast_or_null<ParmVarDecl>( + Importer.Import(E->getParam())); + if (!Param) + return nullptr; + + return CXXDefaultArgExpr::Create( + Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param); +} + +Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo()); + if (!TypeInfo) + return nullptr; + + return new (Importer.getToContext()) CXXScalarValueInitExpr( + T, TypeInfo, Importer.Import(E->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr) + return nullptr; + + auto *Dtor = cast_or_null<CXXDestructorDecl>( + Importer.Import(const_cast<CXXDestructorDecl *>( + E->getTemporary()->getDestructor()))); + if (!Dtor) + return nullptr; + + ASTContext &ToCtx = Importer.getToContext(); + CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor); + return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr); +} + +Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) { + QualType T = Importer.Import(CE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 8> Args(CE->getNumArgs()); + if (ImportContainerChecked(CE->arguments(), Args)) + return nullptr; + + auto *Ctor = cast_or_null<CXXConstructorDecl>( + Importer.Import(CE->getConstructor())); + if (!Ctor) + return nullptr; + + return CXXTemporaryObjectExpr::Create( + Importer.getToContext(), T, + Importer.Import(CE->getLocStart()), + Ctor, + CE->isElidable(), + Args, + CE->hadMultipleCandidates(), + CE->isListInitialization(), + CE->isStdInitListInitialization(), + CE->requiresZeroInitialization(), + CE->getConstructionKind(), + Importer.Import(CE->getParenOrBraceRange())); +} + +Expr * +ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *TempE = Importer.Import(E->GetTemporaryExpr()); + if (!TempE) + return nullptr; + + ValueDecl *ExtendedBy = cast_or_null<ValueDecl>( + Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl()))); + if (!ExtendedBy && E->getExtendingDecl()) + return nullptr; + + auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( + T, TempE, E->isBoundToLvalueReference()); + + // FIXME: Should ManglingNumber get numbers associated with 'to' context? + ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber()); + return ToMTE; +} + + +Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { + QualType T = Importer.Import(CE->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs()); + if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs)) + return nullptr; + + FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>( + Importer.Import(CE->getOperatorNew())); + if (!OperatorNewDecl && CE->getOperatorNew()) + return nullptr; + + FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + Importer.Import(CE->getOperatorDelete())); + if (!OperatorDeleteDecl && CE->getOperatorDelete()) + return nullptr; + + Expr *ToInit = Importer.Import(CE->getInitializer()); + if (!ToInit && CE->getInitializer()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo()); + if (!TInfo) + return nullptr; + + Expr *ToArrSize = Importer.Import(CE->getArraySize()); + if (!ToArrSize && CE->getArraySize()) + return nullptr; + + return new (Importer.getToContext()) CXXNewExpr( + Importer.getToContext(), + CE->isGlobalNew(), + OperatorNewDecl, OperatorDeleteDecl, + CE->doesUsualArrayDeleteWantSize(), + PlacementArgs, + Importer.Import(CE->getTypeIdParens()), + ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo, + Importer.Import(CE->getSourceRange()), + Importer.Import(CE->getDirectInitRange())); +} + +Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + Importer.Import(E->getOperatorDelete())); + if (!OperatorDeleteDecl && E->getOperatorDelete()) + return nullptr; + + Expr *ToArg = Importer.Import(E->getArgument()); + if (!ToArg && E->getArgument()) + return nullptr; + + return new (Importer.getToContext()) CXXDeleteExpr( + T, E->isGlobalDelete(), + E->isArrayForm(), + E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), + OperatorDeleteDecl, + ToArg, + Importer.Import(E->getLocStart())); } Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { @@ -5849,8 +6378,7 @@ return nullptr; SmallVector<Expr *, 6> ToArgs(E->getNumArgs()); - if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(), - ToArgs.begin())) + if (ImportContainerChecked(E->arguments(), ToArgs)) return nullptr; return CXXConstructExpr::Create(Importer.getToContext(), T, @@ -5864,6 +6392,24 @@ Importer.Import(E->getParenOrBraceRange())); } +Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) { + Expr *SubExpr = Importer.Import(EWC->getSubExpr()); + if (!SubExpr && EWC->getSubExpr()) + return nullptr; + + SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects()); + for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++) + if (ExprWithCleanups::CleanupObject Obj = + cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I)))) + Objs[I] = Obj; + else + return nullptr; + + return ExprWithCleanups::Create(Importer.getToContext(), + SubExpr, EWC->cleanupsHaveSideEffects(), + Objs); +} + Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5874,8 +6420,7 @@ return nullptr; SmallVector<Expr *, 4> ToArgs(E->getNumArgs()); - - if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) + if (ImportContainerChecked(E->arguments(), ToArgs)) return nullptr; return new (Importer.getToContext()) CXXMemberCallExpr( @@ -5976,8 +6521,7 @@ return nullptr; llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); - if (ImportArrayChecked( - ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin())) + if (ImportContainerChecked(ILE->inits(), Exprs)) return nullptr; ASTContext &ToCtx = Importer.getToContext(); @@ -6530,6 +7074,21 @@ } +CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { + auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); + if (Pos != ImportedCXXBaseSpecifiers.end()) + return Pos->second; + + CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier( + Import(BaseSpec->getSourceRange()), + BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(), + BaseSpec->getAccessSpecifierAsWritten(), + Import(BaseSpec->getTypeSourceInfo()), + Import(BaseSpec->getEllipsisLoc())); + ImportedCXXBaseSpecifiers[BaseSpec] = Imported; + return Imported; +} + void ASTImporter::ImportDefinition(Decl *From) { Decl *To = Import(From); if (!To) Index: include/clang/AST/DeclFriend.h =================================================================== --- include/clang/AST/DeclFriend.h +++ include/clang/AST/DeclFriend.h @@ -166,6 +166,7 @@ friend class ASTDeclReader; friend class ASTDeclWriter; + friend class ASTNodeImporter; friend TrailingObjects; }; Index: include/clang/AST/ASTImporter.h =================================================================== --- include/clang/AST/ASTImporter.h +++ include/clang/AST/ASTImporter.h @@ -24,6 +24,7 @@ namespace clang { class ASTContext; class CXXCtorInitializer; + class CXXBaseSpecifier; class Decl; class DeclContext; class DiagnosticsEngine; @@ -39,7 +40,9 @@ class ASTImporter { public: typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet; - + typedef llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *> + ImportedCXXBaseSpecifierMap; + private: /// \brief The contexts we're importing to and from. ASTContext &ToContext, &FromContext; @@ -68,7 +71,12 @@ /// \brief Mapping from the already-imported FileIDs in the "from" source /// manager to the corresponding FileIDs in the "to" source manager. llvm::DenseMap<FileID, FileID> ImportedFileIDs; - + + /// \brief Mapping from the already-imported CXXBasesSpecifier in + /// the "from" source manager to the corresponding CXXBasesSpecifier + /// in the "to" source manager. + ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers; + /// \brief Imported, anonymous tag declarations that are missing their /// corresponding typedefs. SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs; @@ -212,8 +220,13 @@ /// \returns the equivalent initializer in the "to" context. CXXCtorInitializer *Import(CXXCtorInitializer *FromInit); + /// \brief Import the given CXXBaseSpecifier from the "from" context into + /// the "to" context. + /// + /// \returns the equivalent CXXBaseSpecifier in the source manager of the + /// "to" context. + CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec); - /// \brief Import the definition of the given declaration, including all of /// the declarations it contains. ///
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits