a.sidorin removed rL LLVM as the repository for this revision. a.sidorin updated this revision to Diff 50140. a.sidorin added a comment.
Stylish fixes. Serge: ASTMatcher review is complete so there should be no more build problems. Could you try again? Also, I'd prefer to add your changes in the next patch, without splitting. About missing tests: they are planned in later patches too. http://reviews.llvm.org/D14286 Files: include/clang/AST/Type.h lib/AST/ASTImporter.cpp unittests/AST/ASTImporterTest.cpp unittests/AST/CMakeLists.txt unittests/AST/MatchVerifier.h
Index: unittests/AST/MatchVerifier.h =================================================================== --- unittests/AST/MatchVerifier.h +++ unittests/AST/MatchVerifier.h @@ -62,6 +62,9 @@ std::vector<std::string>& Args, Language L); + template <typename MatcherType> + testing::AssertionResult match(const Decl *D, const MatcherType &AMatcher); + protected: void run(const MatchFinder::MatchResult &Result) override; virtual void verify(const MatchFinder::MatchResult &Result, @@ -127,6 +130,22 @@ return testing::AssertionSuccess(); } +/// \brief Runs a matcher over some AST, and returns the result of the +/// verifier for the matched node. +template <typename NodeType> template <typename MatcherType> +testing::AssertionResult MatchVerifier<NodeType>::match( + const Decl *D, const MatcherType &AMatcher) { + MatchFinder Finder; + Finder.addMatcher(AMatcher.bind(""), this); + + setFailure("Could not find match"); + Finder.match(*D, D->getASTContext()); + + if (!Verified) + return testing::AssertionFailure() << VerifyResult; + return testing::AssertionSuccess(); +} + template <typename NodeType> void MatchVerifier<NodeType>::run(const MatchFinder::MatchResult &Result) { const NodeType *Node = Result.Nodes.getNodeAs<NodeType>(""); Index: unittests/AST/CMakeLists.txt =================================================================== --- unittests/AST/CMakeLists.txt +++ unittests/AST/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_unittest(ASTTests ASTContextParentMapTest.cpp + ASTImporterTest.cpp ASTTypeTraitsTest.cpp ASTVectorTest.cpp CommentLexer.cpp Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- /dev/null +++ unittests/AST/ASTImporterTest.cpp @@ -0,0 +1,460 @@ +//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tests for the correct import of AST nodes from one AST context to another. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTImporter.h" +#include "MatchVerifier.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +namespace clang { +namespace ast_matchers { + +using clang::tooling::newFrontendActionFactory; +using clang::tooling::runToolOnCodeWithArgs; +using clang::tooling::FrontendActionFactory; + +typedef std::vector<std::string> StringVector; + +void getLangArgs(Language Lang, StringVector &Args) { + switch (Lang) { + case Lang_C: + Args.insert(Args.end(), { "-x", "c", "-std=c99" }); + break; + case Lang_C89: + Args.insert(Args.end(), { "-x", "c", "-std=c89" }); + break; + case Lang_CXX: + Args.push_back("-std=c++98"); + break; + case Lang_CXX11: + Args.push_back("-std=c++11"); + break; + case Lang_OpenCL: + case Lang_OBJCXX: + break; + } +} + +template<typename NodeType, typename MatcherType> +testing::AssertionResult +testImport(const std::string &FromCode, Language FromLang, + const std::string &ToCode, Language ToLang, + MatchVerifier<NodeType> &Verifier, + const MatcherType &AMatcher) { + StringVector FromArgs, ToArgs; + getLangArgs(FromLang, FromArgs); + getLangArgs(ToLang, ToArgs); + + const char * const InputFileName = "input.cc"; + const char * const OutputFileName = "output.cc"; + + std::unique_ptr<ASTUnit> + FromAST = tooling::buildASTFromCodeWithArgs( + FromCode, FromArgs, InputFileName), + ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName); + + ASTContext &FromCtx = FromAST->getASTContext(), + &ToCtx = ToAST->getASTContext(); + + // Add input.cc to virtual file system so importer can 'find' it + // while importing SourceLocations. + vfs::OverlayFileSystem *OFS = static_cast<vfs::OverlayFileSystem *>( + ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get()); + vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>( + OFS->overlays_begin()->get()); + MFS->addFile(InputFileName, 0, + llvm::MemoryBuffer::getMemBuffer(FromCode.c_str())); + + ASTImporter Importer(ToCtx, ToAST->getFileManager(), + FromCtx, FromAST->getFileManager(), false); + + IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport"); + assert(ImportedII && "Declaration with 'declToImport' name" + "should be specified in test!"); + DeclarationName ImportDeclName(ImportedII); + SmallVector<NamedDecl *, 4> FoundDecls; + FromCtx.getTranslationUnitDecl()->localUncachedLookup( + ImportDeclName, FoundDecls); + + if (FoundDecls.size() != 1) + return testing::AssertionFailure() << "Multiple declarations were found!"; + + auto Imported = Importer.Import(*FoundDecls.begin()); + if (!Imported) + return testing::AssertionFailure() << "Import failed, nullptr returned!"; + + // This should dump source locations and assert if some source locations + // were not imported + SmallString<1024> ImportChecker; + llvm::raw_svector_ostream ToNothing(ImportChecker); + ToCtx.getTranslationUnitDecl()->print(ToNothing); + + return Verifier.match(Imported, AMatcher); +} + +TEST(ImportExpr, ImportStringLiteral) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE(testImport("void declToImport() { \"foo\"; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + stringLiteral( + hasType( + asString("const char [4]"))))))))); + EXPECT_TRUE(testImport("void declToImport() { L\"foo\"; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + stringLiteral( + hasType( + asString("const wchar_t [4]"))))))))); + EXPECT_TRUE(testImport("void declToImport() { \"foo\" \"bar\"; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + stringLiteral( + hasType( + asString("const char [7]"))))))))); +} + +TEST(ImportExpr, ImportGNUNullExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE(testImport("void declToImport() { __null; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + gnuNullExpr( + hasType( + asString("long"))))))))); +} + +TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE(testImport("void declToImport() { nullptr; }", + Lang_CXX11, "", Lang_CXX11, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + cxxNullPtrLiteralExpr())))))); +} + + +TEST(ImportExpr, ImportFloatinglLiteralExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE(testImport("void declToImport() { 1.0; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + floatLiteral( + equals(1.0), + hasType(asString("double"))))))))); + EXPECT_TRUE(testImport("void declToImport() { 1.0e-5f; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + floatLiteral( + equals(1.0e-5f), + hasType(asString("float"))))))))); +} + +TEST(ImportExpr, ImportCompoundLiteralExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport() {" + " struct s { int x; long y; unsigned z; }; " + " (struct s){ 42, 0L, 1U }; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + compoundLiteralExpr( + hasType(asString("struct s")), + has(initListExpr( + hasType(asString("struct s")), + has(integerLiteral( + equals(42), hasType(asString("int")))), + has(integerLiteral( + equals(0), hasType(asString("long")))), + has(integerLiteral( + equals(1), + hasType(asString("unsigned int")))) + ))))))))); +} + +TEST(ImportExpr, ImportCXXThisExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport("class declToImport { void f() { this; } };", + Lang_CXX, "", Lang_CXX, Verifier, + cxxRecordDecl( + hasMethod( + hasBody( + compoundStmt( + has( + cxxThisExpr( + hasType( + asString("class declToImport *")))))))))); +} + +TEST(ImportExpr, ImportAtomicExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + atomicExpr( + has(declRefExpr( + hasDeclaration(varDecl(hasName("ptr"))), + hasType(asString("int *")))), + has(integerLiteral(equals(1), hasType(asString("int")))) + ))))))); +} + +TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport() { loop: goto loop; &&loop; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))), + has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop"))))) + ))))); +} + +TEST(ImportExpr, ImportParenListExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + " template<typename T> class declToImport {" + " void f() { declToImport X(*this); } }; ", + Lang_CXX, "", Lang_CXX, Verifier, + classTemplateDecl( + has( + cxxRecordDecl( + hasMethod( + allOf( + hasName("f"), + hasBody( + compoundStmt( + has( + declStmt( + hasSingleDecl( + varDecl( + hasInitializer( + parenListExpr( + has( + unaryOperator( + hasOperatorName("*"), + hasUnaryOperand(cxxThisExpr()) + ))))))))))))))))); +} + +TEST(ImportExpr, ImportStmtExpr) { + MatchVerifier<Decl> Verifier; + // NOTE: has() ignores implicit casts, using hasDescendant() to match it + EXPECT_TRUE( + testImport( + "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + declStmt( + hasSingleDecl( + varDecl( + hasName("C"), + hasType(asString("int")), + hasInitializer( + stmtExpr( + hasAnySubstatement( + declStmt( + hasSingleDecl( + varDecl( + hasName("X"), + hasType(asString("int")), + hasInitializer( + integerLiteral(equals(4))))))), + hasDescendant( + implicitCastExpr() + )))))))))))); +} + +TEST(ImportExpr, ImportConditionalOperator) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport() { true ? 1 : -5; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + conditionalOperator( + hasCondition(cxxBoolLiteral(equals(true))), + hasTrueExpression(integerLiteral(equals(1))), + hasFalseExpression( + unaryOperator(hasUnaryOperand(integerLiteral(equals(5)))) + )))))))); +} + +TEST(ImportExpr, ImportBinaryConditionalOperator) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport() { 1 ?: -5; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + binaryConditionalOperator( + hasCondition( + implicitCastExpr( + hasSourceExpression( + opaqueValueExpr( + hasSourceExpression(integerLiteral(equals(1))))), + hasType(booleanType()))), + hasTrueExpression( + opaqueValueExpr(hasSourceExpression( + integerLiteral(equals(1))))), + hasFalseExpression( + unaryOperator(hasOperatorName("-"), + hasUnaryOperand(integerLiteral(equals(5))))) + ))))))); +} + +TEST(ImportExpr, ImportDesignatedInitExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE(testImport("void declToImport() {" + " struct point { double x; double y; };" + " struct point ptarray[10] = " + "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }", + Lang_C, "", Lang_C, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + declStmt( + hasSingleDecl( + varDecl( + hasInitializer( + initListExpr( + hasSyntacticForm( + initListExpr( + has( + designatedInitExpr( + designatorCountIs(2), + has(floatLiteral( + equals(1.0))), + has(integerLiteral( + equals(2))))), + has( + designatedInitExpr( + designatorCountIs(2), + has(floatLiteral( + equals(2.0))), + has(integerLiteral( + equals(2))))), + has( + designatedInitExpr( + designatorCountIs(2), + has(floatLiteral( + equals(1.0))), + has(integerLiteral( + equals(0))))) + ))))))))))))); +} + + +TEST(ImportExpr, ImportPredefinedExpr) { + MatchVerifier<Decl> Verifier; + // __func__ expands as StringLiteral("declToImport") + EXPECT_TRUE(testImport("void declToImport() { __func__; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + predefinedExpr( + hasType( + asString("const char [13]")), + has( + stringLiteral( + hasType( + asString("const char [13]"))))))))))); +} + +TEST(ImportExpr, ImportInitListExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "void declToImport() {" + " struct point { double x; double y; };" + " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0," + " [0].x = 1.0 }; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + hasBody( + compoundStmt( + has( + declStmt( + hasSingleDecl( + varDecl( + hasInitializer( + initListExpr( + has( + cxxConstructExpr( + requiresZeroInitialization())), + has( + initListExpr( + hasType(asString("struct point")), + has(floatLiteral(equals(1.0))), + has(implicitValueInitExpr( + hasType(asString("double")))))), + has( + initListExpr( + hasType(asString("struct point")), + has(floatLiteral(equals(2.0))), + has(floatLiteral(equals(1.0))))) + ))))))))))); +} + + +} // end namespace ast_matchers +} // end namespace clang Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -29,7 +29,16 @@ public DeclVisitor<ASTNodeImporter, Decl *>, public StmtVisitor<ASTNodeImporter, Stmt *> { ASTImporter &Importer; - + + template<class ItemT, typename IIter, typename OIter> + void ImportMultipleItems(IIter Ibegin, IIter Iend, OIter Obegin) { + ASTImporter &ImporterRef = Importer; + std::transform(Ibegin, Iend, Obegin, + [&ImporterRef](ItemT I) -> ItemT { + return ImporterRef.Import(I); + }); + } + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { } @@ -64,11 +73,12 @@ QualType VisitDecltypeType(const DecltypeType *T); QualType VisitUnaryTransformType(const UnaryTransformType *T); QualType VisitAutoType(const AutoType *T); + QualType VisitInjectedClassNameType(const InjectedClassNameType *T); // FIXME: DependentDecltypeType QualType VisitRecordType(const RecordType *T); QualType VisitEnumType(const EnumType *T); QualType VisitAttributedType(const AttributedType *T); - // FIXME: TemplateTypeParmType + QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T); // FIXME: SubstTemplateTypeParmType QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); QualType VisitElaboratedType(const ElaboratedType *T); @@ -86,6 +96,10 @@ void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + + typedef DesignatedInitExpr::Designator Designator; + Designator ImportDesignator(const Designator &D); + /// \brief What we should import from the definition. enum ImportDefinitionKind { @@ -136,6 +150,7 @@ Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitTypeAliasDecl(TypeAliasDecl *D); + Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitEnumDecl(EnumDecl *D); Decl *VisitRecordDecl(RecordDecl *D); Decl *VisitEnumConstantDecl(EnumConstantDecl *D); @@ -175,6 +190,7 @@ DeclGroupRef ImportDeclGroup(DeclGroupRef DG); Stmt *VisitStmt(Stmt *S); + Stmt *VisitGCCAsmStmt(GCCAsmStmt *S); Stmt *VisitDeclStmt(DeclStmt *S); Stmt *VisitNullStmt(NullStmt *S); Stmt *VisitCompoundStmt(CompoundStmt *S); @@ -192,7 +208,6 @@ Stmt *VisitContinueStmt(ContinueStmt *S); Stmt *VisitBreakStmt(BreakStmt *S); Stmt *VisitReturnStmt(ReturnStmt *S); - // FIXME: GCCAsmStmt // FIXME: MSAsmStmt // FIXME: SEHExceptStmt // FIXME: SEHFinallyStmt @@ -213,23 +228,64 @@ // Importing expressions Expr *VisitExpr(Expr *E); + Expr *VisitVAArgExpr(VAArgExpr *E); + Expr *VisitGNUNullExpr(GNUNullExpr *E); + Expr *VisitPredefinedExpr(PredefinedExpr *E); Expr *VisitDeclRefExpr(DeclRefExpr *E); + Expr *VisitInitListExpr(InitListExpr *ILE); + Expr *VisitImplicitValueInitExpr(ImplicitValueInitExpr *ILE); + Expr *VisitDesignatedInitExpr(DesignatedInitExpr *E); + Expr *VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); + Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); Expr *VisitIntegerLiteral(IntegerLiteral *E); + Expr *VisitFloatingLiteral(FloatingLiteral *E); Expr *VisitCharacterLiteral(CharacterLiteral *E); + Expr *VisitStringLiteral(StringLiteral *E); + Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E); + Expr *VisitAtomicExpr(AtomicExpr *E); + Expr *VisitAddrLabelExpr(AddrLabelExpr *E); Expr *VisitParenExpr(ParenExpr *E); + Expr *VisitParenListExpr(ParenListExpr *E); + Expr *VisitStmtExpr(StmtExpr *E); Expr *VisitUnaryOperator(UnaryOperator *E); Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); Expr *VisitBinaryOperator(BinaryOperator *E); + Expr *VisitConditionalOperator(ConditionalOperator *E); + Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E); + Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E); Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); Expr *VisitCStyleCastExpr(CStyleCastExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitMemberExpr(MemberExpr *E); + Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCallExpr(CallExpr *E); }; } using namespace clang; +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +namespace { + +template<typename IIter> +static bool containsNullPtr(IIter Ibegin, IIter Iend) { + return std::find(Ibegin, Iend, nullptr) == Iend; +} + +template<typename IIter, typename OIter> +static bool checkPossibleNull(IIter Ibegin, IIter Iend, OIter Obegin) { + for (; Ibegin != Iend; Ibegin++, Obegin++) + if (*Obegin == nullptr && Ibegin != nullptr) + return false; + return true; +} + +} // end anonymous namespace + + //---------------------------------------------------------------------------- // Structural Equivalence //---------------------------------------------------------------------------- @@ -1759,6 +1815,28 @@ /*IsDependent*/false); } +QualType ASTNodeImporter::VisitInjectedClassNameType( + const InjectedClassNameType *T) { + CXXRecordDecl *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl())); + if (!D) + return QualType(); + + QualType InjType = Importer.Import(T->getInjectedSpecializationType()); + if (InjType.isNull()) + return QualType(); + + // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading + // See comments in InjectedClassNameType definition for details + // return Importer.getToContext().getInjectedClassNameType(D, InjType); + enum { + TypeAlignmentInBits = 4, + TypeAlignment = 1 << TypeAlignmentInBits + }; + + return QualType(new (Importer.getToContext(), TypeAlignment) + InjectedClassNameType(D, InjType), 0); +} + QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { RecordDecl *ToDecl = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl())); @@ -1798,6 +1876,18 @@ ToModifiedType, ToEquivalentType); } + +QualType ASTNodeImporter::VisitTemplateTypeParmType( + const TemplateTypeParmType *T) { + TemplateTypeParmDecl *ParmDecl = + cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl())); + if (!ParmDecl && T->getDecl()) + return QualType(); + + return Importer.getToContext().getTemplateTypeParmType( + T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl); +} + QualType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { TemplateName ToTemplate = Importer.Import(T->getTemplateName()); @@ -2493,6 +2583,39 @@ return VisitTypedefNameDecl(D, /*IsAlias=*/true); } +Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { + // Import the major distinguishing characteristics of this label. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + assert(LexicalDC->isFunctionOrMethod()); + + LabelDecl *ToLabel = D->isGnuLocal() + ? LabelDecl::Create(Importer.getToContext(), + DC, Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(D->getLocStart())) + : LabelDecl::Create(Importer.getToContext(), + DC, Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo()); + Importer.Imported(D, ToLabel); + + LabelStmt *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); + if (!Label) + return nullptr; + + ToLabel->setStmt(Label); + ToLabel->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToLabel); + return ToLabel; +} + Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the major distinguishing characteristics of this enum. DeclContext *DC, *LexicalDC; @@ -4281,16 +4404,16 @@ CXXRecordDecl *DTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. - SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); - SourceLocation IdLoc = Importer.Import(DTemplated->getLocation()); - CXXRecordDecl *D2Templated = CXXRecordDecl::Create(Importer.getToContext(), - DTemplated->getTagKind(), - DC, StartLoc, IdLoc, - Name.getAsIdentifierInfo()); - D2Templated->setAccess(DTemplated->getAccess()); - D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); - D2Templated->setLexicalDeclContext(LexicalDC); - + // Create the declaration that is being templated. + CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>( + Importer.Import(DTemplated)); + if (!D2Templated) + return nullptr; + + // Resolve possible cyclic import. + if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) + return AlreadyImported; + // Create the class template declaration itself. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); @@ -4634,7 +4757,84 @@ << S->getStmtClassName(); return nullptr; } - + + +Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { + SmallVector<IdentifierInfo *, 4> Names; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { + IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); + if (!ToII) + return nullptr; + Names.push_back(ToII); + } + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { + IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I)); + if (!ToII) + return nullptr; + Names.push_back(ToII); + } + + SmallVector<StringLiteral *, 4> Clobbers; + for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) { + StringLiteral *Clobber = cast_or_null<StringLiteral>( + Importer.Import(S->getClobberStringLiteral(I))); + if (!Clobber) + return nullptr; + Clobbers.push_back(Clobber); + } + + SmallVector<StringLiteral *, 4> Constraints; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { + StringLiteral *Output = cast_or_null<StringLiteral>( + Importer.Import(S->getOutputConstraintLiteral(I))); + if (!Output) + return nullptr; + Constraints.push_back(Output); + } + + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { + StringLiteral *Input = cast_or_null<StringLiteral>( + Importer.Import(S->getInputConstraintLiteral(I))); + if (!Input) + return nullptr; + Constraints.push_back(Input); + } + + SmallVector<Expr *, 4> Exprs; + for (int I = 0, E = S->getNumOutputs(); I != E; I++) { + if (Expr *Out = Importer.Import(S->getOutputExpr(I))) + Exprs.push_back(Out); + else + return nullptr; + } + for (int I = 0, E = S->getNumInputs(); I != E; I++) { + if (Expr *Input = Importer.Import(S->getInputExpr(I))) + Exprs.push_back(Input); + else + return nullptr; + } + + StringLiteral *AsmStr = cast_or_null<StringLiteral>( + Importer.Import(S->getAsmString())); + if (!AsmStr) + return nullptr; + + return new (Importer.getToContext()) GCCAsmStmt( + Importer.getToContext(), + Importer.Import(S->getAsmLoc()), + S->isSimple(), + S->isVolatile(), + S->getNumOutputs(), + S->getNumInputs(), + Names.data(), + Constraints.data(), + Exprs.data(), + AsmStr, + S->getNumClobbers(), + Clobbers.data(), + Importer.Import(S->getRParenLoc())); +} + Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup()); for (Decl *ToD : ToDG) { @@ -5077,6 +5277,48 @@ return nullptr; } +Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr && E->getSubExpr()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(E->getWrittenTypeInfo()); + if (!TInfo) + return nullptr; + + return new (Importer.getToContext()) VAArgExpr( + Importer.Import(E->getBuiltinLoc()), SubExpr, TInfo, + Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI()); +} + + +Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return new (Importer.getToContext()) GNUNullExpr( + T, Importer.Import(E->getExprLoc())); +} + +Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + StringLiteral *SL = cast_or_null<StringLiteral>( + Importer.Import(E->getFunctionName())); + if (!SL && E->getFunctionName()) + return nullptr; + + return new (Importer.getToContext()) PredefinedExpr( + Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL); +} + Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); if (!ToD) @@ -5107,6 +5349,126 @@ return DRE; } + +Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { + QualType T = Importer.Import(ILE->getType()); + if (T.isNull()) + return nullptr; + + llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); + ImportMultipleItems<Expr *>( + ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin()); + if (!checkPossibleNull(ILE->begin(), ILE->end(), Exprs.begin())) + return nullptr; + + ASTContext &ToCtx = Importer.getToContext(); + InitListExpr *To = new (ToCtx) InitListExpr( + ToCtx, Importer.Import(ILE->getLBraceLoc()), + Exprs, Importer.Import(ILE->getLBraceLoc())); + To->setType(T); + + if (ILE->hasArrayFiller()) { + Expr *Filler = Importer.Import(ILE->getArrayFiller()); + if (!Filler) + return nullptr; + To->setArrayFiller(Filler); + } + + if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) { + FieldDecl *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD)); + if (!ToFD) + return nullptr; + To->setInitializedFieldInUnion(ToFD); + } + + if (InitListExpr *SyntForm = ILE->getSyntacticForm()) { + InitListExpr *ToSyntForm = cast_or_null<InitListExpr>( + Importer.Import(SyntForm)); + if (!ToSyntForm) + return nullptr; + To->setSyntacticForm(ToSyntForm); + } + + To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator()); + To->setValueDependent(ILE->isValueDependent()); + To->setInstantiationDependent(ILE->isInstantiationDependent()); + + return To; +} + +Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return NULL; + + return new (Importer.getToContext()) ImplicitValueInitExpr(T); +} + +ASTNodeImporter::Designator +ASTNodeImporter::ImportDesignator(const Designator &D) { + if (D.isFieldDesignator()) { + IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName()); + // Caller checks for import error + return Designator(ToFieldName, Importer.Import(D.getDotLoc()), + Importer.Import(D.getFieldLoc())); + } + if (D.isArrayDesignator()) + return Designator(D.getFirstExprIndex(), + Importer.Import(D.getLBracketLoc()), + Importer.Import(D.getRBracketLoc())); + + assert(D.isArrayRangeDesignator()); + return Designator(D.getFirstExprIndex(), + Importer.Import(D.getLBracketLoc()), + Importer.Import(D.getEllipsisLoc()), + Importer.Import(D.getRBracketLoc())); +} + + +Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) { + Expr *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit())); + if (!Init) + return nullptr; + + SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1); + // List elements from the second, the first is Init itself + for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) { + if (Expr *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I)))) + IndexExprs[I - 1] = Arg; + else + return nullptr; + } + + SmallVector<Designator, 4> Designators(DIE->size()); + std::transform(DIE->designators_begin(), DIE->designators_end(), + Designators.begin(), + [this](const Designator &D) -> Designator { + return ImportDesignator(D); + }); + + for (auto I = DIE->designators_begin(), E = DIE->designators_end(); I != E; + ++I) + if (I->isFieldDesignator() && !I->getFieldName()) + return nullptr; + + return DesignatedInitExpr::Create( + Importer.getToContext(), Designators.data(), Designators.size(), + IndexExprs, Importer.Import(DIE->getEqualOrColonLoc()), + DIE->usesGNUSyntax(), Init); +} + +Expr *ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { + ASTContext &ToCtx = Importer.getToContext(); + return new(ToCtx) CXXNullPtrLiteralExpr(ToCtx.NullPtrTy, + Importer.Import(E->getLocation())); +} + +Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + ASTContext &ToCtx = Importer.getToContext(); + return new (ToCtx) CXXBoolLiteralExpr(E->getValue(), ToCtx.BoolTy, + Importer.Import(E->getLocation())); +} + Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5117,6 +5479,16 @@ Importer.Import(E->getLocation())); } +Expr *ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return FloatingLiteral::Create(Importer.getToContext(), + E->getValue(), E->isExact(), T, + Importer.Import(E->getLocation())); +} + Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5127,6 +5499,69 @@ Importer.Import(E->getLocation())); } +Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated()); + ImportMultipleItems<SourceLocation>(E->tokloc_begin(), E->tokloc_end(), + Locations.begin()); + + return StringLiteral::Create(Importer.getToContext(), E->getBytes(), + E->getKind(), E->isPascal(), T, + Locations.data(), Locations.size()); +} + +Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo()); + if (!TInfo) + return nullptr; + + Expr *Init = Importer.Import(E->getInitializer()); + if (!Init) + return nullptr; + + return new (Importer.getToContext()) CompoundLiteralExpr( + Importer.Import(E->getLParenLoc()), TInfo, T, E->getValueKind(), + Init, E->isFileScope()); +} + +Expr *ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 6> Exprs(E->getNumSubExprs()); + ImportMultipleItems<Expr *>( + E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(), + Exprs.begin()); + if (!containsNullPtr(Exprs.begin(), Exprs.end())) + return nullptr; + + return new (Importer.getToContext()) AtomicExpr( + Importer.Import(E->getBuiltinLoc()), Exprs, T, E->getOp(), + Importer.Import(E->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + LabelDecl *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel())); + if (!ToLabel) + return nullptr; + + return new (Importer.getToContext()) AddrLabelExpr( + Importer.Import(E->getAmpAmpLoc()), Importer.Import(E->getLabelLoc()), + ToLabel, T); +} + Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) @@ -5138,6 +5573,32 @@ SubExpr); } +Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { + SmallVector<Expr *, 4> Exprs(E->getNumExprs()); + ImportMultipleItems<Expr *>(E->getExprs(), E->getExprs() + E->getNumExprs(), + Exprs.begin()); + if (!containsNullPtr(Exprs.begin(), Exprs.end())) + return nullptr; + + return new (Importer.getToContext()) ParenListExpr( + Importer.getToContext(), Importer.Import(E->getLParenLoc()), + Exprs, Importer.Import(E->getLParenLoc())); +} + +Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + CompoundStmt *ToSubStmt = cast_or_null<CompoundStmt>( + Importer.Import(E->getSubStmt())); + if (!ToSubStmt && E->getSubStmt()) + return nullptr; + + return new (Importer.getToContext()) StmtExpr(ToSubStmt, T, + Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc())); +} + Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5198,6 +5659,76 @@ E->isFPContractable()); } +Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *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; + + Expr *ToCond = Importer.Import(E->getCond()); + if (!ToCond) + return nullptr; + + return new (Importer.getToContext()) ConditionalOperator( + ToCond, Importer.Import(E->getQuestionLoc()), + ToLHS, Importer.Import(E->getColonLoc()), + ToRHS, T, E->getValueKind(), E->getObjectKind()); +} + +Expr *ASTNodeImporter::VisitBinaryConditionalOperator( + BinaryConditionalOperator *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *Common = Importer.Import(E->getCommon()); + if (!Common) + return nullptr; + + Expr *Cond = Importer.Import(E->getCond()); + if (!Cond) + return nullptr; + + OpaqueValueExpr *OpaqueValue = cast_or_null<OpaqueValueExpr>( + Importer.Import(E->getOpaqueValue())); + if (!OpaqueValue) + return nullptr; + + Expr *TrueExpr = Importer.Import(E->getTrueExpr()); + if (!TrueExpr) + return nullptr; + + Expr *FalseExpr = Importer.Import(E->getFalseExpr()); + if (!FalseExpr) + return nullptr; + + return new (Importer.getToContext()) BinaryConditionalOperator( + Common, OpaqueValue, Cond, TrueExpr, FalseExpr, + Importer.Import(E->getQuestionLoc()), Importer.Import(E->getColonLoc()), + T, E->getValueKind(), E->getObjectKind()); +} + +Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SourceExpr = Importer.Import(E->getSourceExpr()); + if (!SourceExpr && E->getSourceExpr()) + return nullptr; + + return new (Importer.getToContext()) OpaqueValueExpr( + Importer.Import(E->getExprLoc()), T, E->getValueKind(), + E->getObjectKind(), SourceExpr); +} + Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5344,6 +5875,15 @@ E->getObjectKind()); } +Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return new (Importer.getToContext()) CXXThisExpr( + Importer.Import(E->getExprLoc()), T, E->isImplicit()); +} + Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -4253,6 +4253,8 @@ friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not // currently suitable for AST reading, too much // interdependencies. + friend class ASTNodeImporter; + InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), /*Dependent=*/true, /*InstantiationDependent=*/true,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits