diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2016-04-14 11:51:27 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2016-04-14 11:51:27 +0000 |
commit | 4e7c6fdeeb89d223258f5f68ece38764f332b295 (patch) | |
tree | 6eb4d7cbeb0f12b154ae64d2a1147cc41ba159d8 /clang/unittests/AST/ASTImporterTest.cpp | |
parent | 909d080d98acf3508b3e8d76b2c2b3371e17f618 (diff) | |
download | bcm5719-llvm-4e7c6fdeeb89d223258f5f68ece38764f332b295.tar.gz bcm5719-llvm-4e7c6fdeeb89d223258f5f68ece38764f332b295.zip |
[ASTImporter] Implement some expression-related AST node import.
Introduce ASTImporter unit test framework.
Fix a memory leak introduced in cf8ccff5: an array is allocated
in ImportArray and never freed.
Support new node kinds:
- GCCAsmStmt
- AddrLabelExpr
- AtomicExpr
- CompoundLiteralExpr
- CXXBoolLiteralExpr
- CXXNullPtrLiteralExpr
- CXXThisExpr
- DesignatedInitExpr
- GNUNullExpr
- ImplicitValueInitExpr
- InitListExpr
- OpaqueValueExpr
- PredefinedExpr
- ParenListExpr
- StmtExpr
- VAArgExpr
- BinaryConditionalOperator
- ConditionalOperator
- FloatingLiteral
- StringLiteral
- InjectedClassNameType
- TemplateTypeParmType
- LabelDecl
Patch by Aleksei Sidorin!
Differential Revision: http://reviews.llvm.org/D14286
llvm-svn: 266292
Diffstat (limited to 'clang/unittests/AST/ASTImporterTest.cpp')
-rw-r--r-- | clang/unittests/AST/ASTImporterTest.cpp | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp new file mode 100644 index 00000000000..f5dee659e0e --- /dev/null +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -0,0 +1,470 @@ +//===- 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(isInteger())))))))); +} + +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"))))) + ))))); +} + +AST_MATCHER_P(TemplateDecl, hasTemplateDecl, + internal::Matcher<NamedDecl>, InnerMatcher) { + const NamedDecl *Template = Node.getTemplatedDecl(); + return Template && InnerMatcher.matches(*Template, Finder, Builder); +} + +TEST(ImportExpr, ImportParenListExpr) { + MatchVerifier<Decl> Verifier; + EXPECT_TRUE( + testImport( + "template<typename T> class dummy { void f() { dummy X(*this); } };" + "typedef dummy<int> declToImport;" + "template class dummy<int>;", + Lang_CXX, "", Lang_CXX, Verifier, + typedefDecl( + hasType( + templateSpecializationType( + hasDeclaration( + classTemplateDecl( + hasTemplateDecl( + 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 |