Home | History | Annotate | Download | only in AST
      1 //===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // Tests for the correct import of AST nodes from one AST context to another.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/AST/ASTContext.h"
     15 #include "clang/AST/ASTImporter.h"
     16 #include "MatchVerifier.h"
     17 #include "clang/ASTMatchers/ASTMatchFinder.h"
     18 #include "clang/ASTMatchers/ASTMatchers.h"
     19 #include "clang/Tooling/Tooling.h"
     20 #include "gtest/gtest.h"
     21 
     22 namespace clang {
     23 namespace ast_matchers {
     24 
     25 typedef std::vector<std::string> StringVector;
     26 
     27 void getLangArgs(Language Lang, StringVector &Args) {
     28   switch (Lang) {
     29   case Lang_C:
     30     Args.insert(Args.end(), { "-x", "c", "-std=c99" });
     31     break;
     32   case Lang_C89:
     33     Args.insert(Args.end(), { "-x", "c", "-std=c89" });
     34     break;
     35   case Lang_CXX:
     36     Args.push_back("-std=c++98");
     37     break;
     38   case Lang_CXX11:
     39     Args.push_back("-std=c++11");
     40     break;
     41   case Lang_OpenCL:
     42   case Lang_OBJCXX:
     43     break;
     44   }
     45 }
     46 
     47 template<typename NodeType, typename MatcherType>
     48 testing::AssertionResult
     49 testImport(const std::string &FromCode, Language FromLang,
     50            const std::string &ToCode, Language ToLang,
     51            MatchVerifier<NodeType> &Verifier,
     52            const MatcherType &AMatcher) {
     53   StringVector FromArgs, ToArgs;
     54   getLangArgs(FromLang, FromArgs);
     55   getLangArgs(ToLang, ToArgs);
     56 
     57   const char *const InputFileName = "input.cc";
     58   const char *const OutputFileName = "output.cc";
     59 
     60   std::unique_ptr<ASTUnit>
     61       FromAST = tooling::buildASTFromCodeWithArgs(
     62         FromCode, FromArgs, InputFileName),
     63       ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
     64 
     65   ASTContext &FromCtx = FromAST->getASTContext(),
     66       &ToCtx = ToAST->getASTContext();
     67 
     68   // Add input.cc to virtual file system so importer can 'find' it
     69   // while importing SourceLocations.
     70   vfs::OverlayFileSystem *OFS = static_cast<vfs::OverlayFileSystem *>(
     71         ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
     72   vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>(
     73         OFS->overlays_begin()->get());
     74   MFS->addFile(InputFileName, 0,
     75                llvm::MemoryBuffer::getMemBuffer(FromCode.c_str()));
     76 
     77   ASTImporter Importer(ToCtx, ToAST->getFileManager(),
     78                        FromCtx, FromAST->getFileManager(), false);
     79 
     80   IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport");
     81   assert(ImportedII && "Declaration with 'declToImport' name"
     82                        "should be specified in test!");
     83   DeclarationName ImportDeclName(ImportedII);
     84   SmallVector<NamedDecl *, 4> FoundDecls;
     85   FromCtx.getTranslationUnitDecl()->localUncachedLookup(
     86         ImportDeclName, FoundDecls);
     87 
     88   if (FoundDecls.size() != 1)
     89     return testing::AssertionFailure() << "Multiple declarations were found!";
     90 
     91   auto Imported = Importer.Import(*FoundDecls.begin());
     92   if (!Imported)
     93     return testing::AssertionFailure() << "Import failed, nullptr returned!";
     94 
     95   // This should dump source locations and assert if some source locations
     96   // were not imported
     97   SmallString<1024> ImportChecker;
     98   llvm::raw_svector_ostream ToNothing(ImportChecker);
     99   ToCtx.getTranslationUnitDecl()->print(ToNothing);
    100 
    101   return Verifier.match(Imported, AMatcher);
    102 }
    103 
    104 TEST(ImportExpr, ImportStringLiteral) {
    105   MatchVerifier<Decl> Verifier;
    106   EXPECT_TRUE(testImport("void declToImport() { \"foo\"; }",
    107                          Lang_CXX, "", Lang_CXX, Verifier,
    108                          functionDecl(
    109                            hasBody(
    110                              compoundStmt(
    111                                has(
    112                                  stringLiteral(
    113                                    hasType(
    114                                      asString("const char [4]")))))))));
    115   EXPECT_TRUE(testImport("void declToImport() { L\"foo\"; }",
    116                          Lang_CXX, "", Lang_CXX, Verifier,
    117                          functionDecl(
    118                            hasBody(
    119                              compoundStmt(
    120                                has(
    121                                  stringLiteral(
    122                                    hasType(
    123                                      asString("const wchar_t [4]")))))))));
    124   EXPECT_TRUE(testImport("void declToImport() { \"foo\" \"bar\"; }",
    125                          Lang_CXX, "", Lang_CXX, Verifier,
    126                          functionDecl(
    127                            hasBody(
    128                              compoundStmt(
    129                                has(
    130                                  stringLiteral(
    131                                    hasType(
    132                                      asString("const char [7]")))))))));
    133 }
    134 
    135 TEST(ImportExpr, ImportGNUNullExpr) {
    136   MatchVerifier<Decl> Verifier;
    137   EXPECT_TRUE(testImport("void declToImport() { __null; }",
    138                          Lang_CXX, "", Lang_CXX, Verifier,
    139                          functionDecl(
    140                            hasBody(
    141                              compoundStmt(
    142                                has(
    143                                  gnuNullExpr(
    144                                    hasType(isInteger()))))))));
    145 }
    146 
    147 TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
    148   MatchVerifier<Decl> Verifier;
    149   EXPECT_TRUE(testImport("void declToImport() { nullptr; }",
    150                          Lang_CXX11, "", Lang_CXX11, Verifier,
    151                          functionDecl(
    152                            hasBody(
    153                              compoundStmt(
    154                                has(
    155                                  cxxNullPtrLiteralExpr()))))));
    156 }
    157 
    158 
    159 TEST(ImportExpr, ImportFloatinglLiteralExpr) {
    160   MatchVerifier<Decl> Verifier;
    161   EXPECT_TRUE(testImport("void declToImport() { 1.0; }",
    162                          Lang_CXX, "", Lang_CXX, Verifier,
    163                          functionDecl(
    164                            hasBody(
    165                              compoundStmt(
    166                                has(
    167                                  floatLiteral(
    168                                    equals(1.0),
    169                                    hasType(asString("double")))))))));
    170   EXPECT_TRUE(testImport("void declToImport() { 1.0e-5f; }",
    171                          Lang_CXX, "", Lang_CXX, Verifier,
    172                          functionDecl(
    173                            hasBody(
    174                              compoundStmt(
    175                                has(
    176                                  floatLiteral(
    177                                    equals(1.0e-5f),
    178                                    hasType(asString("float")))))))));
    179 }
    180 
    181 TEST(ImportExpr, ImportCompoundLiteralExpr) {
    182   MatchVerifier<Decl> Verifier;
    183   EXPECT_TRUE(
    184         testImport(
    185           "void declToImport() {"
    186           "  struct s { int x; long y; unsigned z; }; "
    187           "  (struct s){ 42, 0L, 1U }; }",
    188           Lang_CXX, "", Lang_CXX, Verifier,
    189           functionDecl(
    190             hasBody(
    191               compoundStmt(
    192                 has(
    193                   compoundLiteralExpr(
    194                     hasType(asString("struct s")),
    195                     has(initListExpr(
    196                       hasType(asString("struct s")),
    197                       has(integerLiteral(
    198                             equals(42), hasType(asString("int")))),
    199                       has(integerLiteral(
    200                             equals(0), hasType(asString("long")))),
    201                       has(integerLiteral(
    202                             equals(1),
    203                             hasType(asString("unsigned int"))))
    204                       )))))))));
    205 }
    206 
    207 TEST(ImportExpr, ImportCXXThisExpr) {
    208   MatchVerifier<Decl> Verifier;
    209   EXPECT_TRUE(
    210         testImport("class declToImport { void f() { this; } };",
    211                    Lang_CXX, "", Lang_CXX, Verifier,
    212                    cxxRecordDecl(
    213                      hasMethod(
    214                        hasBody(
    215                          compoundStmt(
    216                            has(
    217                              cxxThisExpr(
    218                                hasType(
    219                                  asString("class declToImport *"))))))))));
    220 }
    221 
    222 TEST(ImportExpr, ImportAtomicExpr) {
    223   MatchVerifier<Decl> Verifier;
    224   EXPECT_TRUE(testImport(
    225       "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_CXX,
    226       "", Lang_CXX, Verifier,
    227       functionDecl(hasBody(compoundStmt(has(atomicExpr(
    228           has(ignoringParenImpCasts(
    229               declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
    230                           hasType(asString("int *"))))),
    231           has(integerLiteral(equals(1), hasType(asString("int")))))))))));
    232 }
    233 
    234 TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
    235   MatchVerifier<Decl> Verifier;
    236   EXPECT_TRUE(
    237         testImport(
    238           "void declToImport() { loop: goto loop; &&loop; }",
    239           Lang_CXX, "", Lang_CXX, Verifier,
    240           functionDecl(
    241             hasBody(
    242               compoundStmt(
    243                 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
    244                 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))
    245                 )))));
    246 }
    247 
    248 AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
    249               internal::Matcher<NamedDecl>, InnerMatcher) {
    250   const NamedDecl *Template = Node.getTemplatedDecl();
    251   return Template && InnerMatcher.matches(*Template, Finder, Builder);
    252 }
    253 
    254 TEST(ImportExpr, ImportParenListExpr) {
    255   MatchVerifier<Decl> Verifier;
    256   EXPECT_TRUE(
    257         testImport(
    258           "template<typename T> class dummy { void f() { dummy X(*this); } };"
    259           "typedef dummy<int> declToImport;"
    260           "template class dummy<int>;",
    261           Lang_CXX, "", Lang_CXX, Verifier,
    262           typedefDecl(
    263             hasType(
    264               templateSpecializationType(
    265                 hasDeclaration(
    266                   classTemplateDecl(
    267                     hasTemplateDecl(
    268                       cxxRecordDecl(
    269                         hasMethod(
    270                         allOf(
    271                           hasName("f"),
    272                           hasBody(
    273                             compoundStmt(
    274                               has(
    275                                 declStmt(
    276                                   hasSingleDecl(
    277                                     varDecl(
    278                                       hasInitializer(
    279                                         parenListExpr(
    280                                           has(
    281                                             unaryOperator(
    282                                               hasOperatorName("*"),
    283                                               hasUnaryOperand(cxxThisExpr())
    284                                               )))))))))))))))))))));
    285 }
    286 
    287 TEST(ImportExpr, ImportStmtExpr) {
    288   MatchVerifier<Decl> Verifier;
    289   // NOTE: has() ignores implicit casts, using hasDescendant() to match it
    290   EXPECT_TRUE(
    291         testImport(
    292           "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
    293           Lang_CXX, "", Lang_CXX, Verifier,
    294           functionDecl(
    295             hasBody(
    296               compoundStmt(
    297                 has(
    298                   declStmt(
    299                     hasSingleDecl(
    300                       varDecl(
    301                         hasName("C"),
    302                         hasType(asString("int")),
    303                         hasInitializer(
    304                           stmtExpr(
    305                             hasAnySubstatement(
    306                               declStmt(
    307                                 hasSingleDecl(
    308                                   varDecl(
    309                                     hasName("X"),
    310                                     hasType(asString("int")),
    311                                     hasInitializer(
    312                                       integerLiteral(equals(4))))))),
    313                             hasDescendant(
    314                               implicitCastExpr()
    315                               ))))))))))));
    316 }
    317 
    318 TEST(ImportExpr, ImportConditionalOperator) {
    319   MatchVerifier<Decl> Verifier;
    320   EXPECT_TRUE(
    321         testImport(
    322           "void declToImport() { true ? 1 : -5; }",
    323           Lang_CXX, "", Lang_CXX, Verifier,
    324           functionDecl(
    325             hasBody(
    326               compoundStmt(
    327                 has(
    328                   conditionalOperator(
    329                     hasCondition(cxxBoolLiteral(equals(true))),
    330                     hasTrueExpression(integerLiteral(equals(1))),
    331                     hasFalseExpression(
    332                       unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
    333                       ))))))));
    334 }
    335 
    336 TEST(ImportExpr, ImportBinaryConditionalOperator) {
    337   MatchVerifier<Decl> Verifier;
    338   EXPECT_TRUE(
    339         testImport(
    340           "void declToImport() { 1 ?: -5; }",
    341           Lang_CXX, "", Lang_CXX, Verifier,
    342           functionDecl(
    343             hasBody(
    344               compoundStmt(
    345                 has(
    346                   binaryConditionalOperator(
    347                     hasCondition(
    348                       implicitCastExpr(
    349                         hasSourceExpression(
    350                           opaqueValueExpr(
    351                             hasSourceExpression(integerLiteral(equals(1))))),
    352                         hasType(booleanType()))),
    353                     hasTrueExpression(
    354                       opaqueValueExpr(hasSourceExpression(
    355                                         integerLiteral(equals(1))))),
    356                     hasFalseExpression(
    357                       unaryOperator(hasOperatorName("-"),
    358                                     hasUnaryOperand(integerLiteral(equals(5)))))
    359                       )))))));
    360 }
    361 
    362 TEST(ImportExpr, ImportDesignatedInitExpr) {
    363   MatchVerifier<Decl> Verifier;
    364   EXPECT_TRUE(testImport("void declToImport() {"
    365                          "  struct point { double x; double y; };"
    366                          "  struct point ptarray[10] = "
    367                                 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
    368                          Lang_C, "", Lang_C, Verifier,
    369                          functionDecl(
    370                            hasBody(
    371                              compoundStmt(
    372                                has(
    373                                  declStmt(
    374                                    hasSingleDecl(
    375                                      varDecl(
    376                                        hasInitializer(
    377                                          initListExpr(
    378                                            hasSyntacticForm(
    379                                              initListExpr(
    380                                                has(
    381                                                  designatedInitExpr(
    382                                                    designatorCountIs(2),
    383                                                    has(floatLiteral(
    384                                                          equals(1.0))),
    385                                                    has(integerLiteral(
    386                                                          equals(2))))),
    387                                                has(
    388                                                  designatedInitExpr(
    389                                                    designatorCountIs(2),
    390                                                    has(floatLiteral(
    391                                                          equals(2.0))),
    392                                                    has(integerLiteral(
    393                                                          equals(2))))),
    394                                                has(
    395                                                  designatedInitExpr(
    396                                                    designatorCountIs(2),
    397                                                    has(floatLiteral(
    398                                                          equals(1.0))),
    399                                                    has(integerLiteral(
    400                                                          equals(0)))))
    401                                                )))))))))))));
    402 }
    403 
    404 
    405 TEST(ImportExpr, ImportPredefinedExpr) {
    406   MatchVerifier<Decl> Verifier;
    407   // __func__ expands as StringLiteral("declToImport")
    408   EXPECT_TRUE(testImport("void declToImport() { __func__; }",
    409                          Lang_CXX, "", Lang_CXX, Verifier,
    410                          functionDecl(
    411                            hasBody(
    412                              compoundStmt(
    413                                has(
    414                                  predefinedExpr(
    415                                    hasType(
    416                                      asString("const char [13]")),
    417                                    has(
    418                                      stringLiteral(
    419                                        hasType(
    420                                          asString("const char [13]")))))))))));
    421 }
    422 
    423 TEST(ImportExpr, ImportInitListExpr) {
    424   MatchVerifier<Decl> Verifier;
    425   EXPECT_TRUE(
    426         testImport(
    427           "void declToImport() {"
    428           "  struct point { double x; double y; };"
    429           "  point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
    430           "                        [0].x = 1.0 }; }",
    431           Lang_CXX, "", Lang_CXX, Verifier,
    432           functionDecl(
    433             hasBody(
    434               compoundStmt(
    435                 has(
    436                   declStmt(
    437                     hasSingleDecl(
    438                       varDecl(
    439                         hasInitializer(
    440                           initListExpr(
    441                             has(
    442                               cxxConstructExpr(
    443                                 requiresZeroInitialization())),
    444                             has(
    445                               initListExpr(
    446                                 hasType(asString("struct point")),
    447                                 has(floatLiteral(equals(1.0))),
    448                                 has(implicitValueInitExpr(
    449                                       hasType(asString("double")))))),
    450                             has(
    451                               initListExpr(
    452                                 hasType(asString("struct point")),
    453                                 has(floatLiteral(equals(2.0))),
    454                                 has(floatLiteral(equals(1.0)))))
    455                               )))))))))));
    456 }
    457 
    458 
    459 } // end namespace ast_matchers
    460 } // end namespace clang
    461