1 //===- unittest/AST/ASTImporterObjCTest.cpp -============================--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Tests for the correct import of AST nodes related to Objective-C and
10 // Objective-C++.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/DeclContextInternals.h"
15 #include "clang/ASTMatchers/ASTMatchers.h"
16 #include "gtest/gtest.h"
17 
18 #include "ASTImporterFixtures.h"
19 
20 using namespace clang::ast_matchers;
21 using namespace clang;
22 
23 namespace {
24 struct ImportObjCDecl : ASTImporterOptionSpecificTestBase {};
25 } // namespace
26 
TEST_P(ImportObjCDecl,ImplicitlyDeclareSelf)27 TEST_P(ImportObjCDecl, ImplicitlyDeclareSelf) {
28   Decl *FromTU = getTuDecl(R"(
29                            __attribute__((objc_root_class))
30                            @interface Root
31                            @end
32                            @interface C : Root
33                              -(void)method;
34                            @end
35                            @implementation C
36                              -(void)method {}
37                            @end
38                            )",
39                            Lang_OBJCXX, "input.mm");
40   auto *FromMethod = LastDeclMatcher<ObjCMethodDecl>().match(
41       FromTU, namedDecl(hasName("method")));
42   ASSERT_TRUE(FromMethod);
43   auto ToMethod = Import(FromMethod, Lang_OBJCXX);
44   ASSERT_TRUE(ToMethod);
45 
46   // Both methods should have their implicit parameters.
47   EXPECT_TRUE(FromMethod->getSelfDecl() != nullptr);
48   EXPECT_TRUE(ToMethod->getSelfDecl() != nullptr);
49 }
50 
TEST_P(ImportObjCDecl,ObjPropertyNameConflict)51 TEST_P(ImportObjCDecl, ObjPropertyNameConflict) {
52   // Tests that properties that share the same name are correctly imported.
53   // This is only possible with one instance and one class property.
54   Decl *FromTU = getTuDecl(R"(
55                            @interface DupProp{}
56                            @property (class) int prop;
57                            @property int prop;
58                            @end
59                            )",
60                            Lang_OBJCXX, "input.mm");
61   auto *FromClass = FirstDeclMatcher<ObjCInterfaceDecl>().match(
62       FromTU, namedDecl(hasName("DupProp")));
63   auto ToClass = Import(FromClass, Lang_OBJCXX);
64   ASSERT_TRUE(ToClass);
65   // We should have one class and one instance property.
66   ASSERT_EQ(
67       1, std::distance(ToClass->classprop_begin(), ToClass->classprop_end()));
68   ASSERT_EQ(1,
69             std::distance(ToClass->instprop_begin(), ToClass->instprop_end()));
70   for (clang::ObjCPropertyDecl *prop : ToClass->properties()) {
71     // All properties should have a getter and a setter.
72     ASSERT_TRUE(prop->getGetterMethodDecl());
73     ASSERT_TRUE(prop->getSetterMethodDecl());
74     // The getters/setters should be able to find the right associated property.
75     ASSERT_EQ(prop->getGetterMethodDecl()->findPropertyDecl(), prop);
76     ASSERT_EQ(prop->getSetterMethodDecl()->findPropertyDecl(), prop);
77   }
78 }
79 
80 static const auto ObjCTestArrayForRunOptions =
81     std::array<std::vector<std::string>, 2>{
82         {std::vector<std::string>{"-fno-objc-arc"},
83          std::vector<std::string>{"-fobjc-arc"}}};
84 
85 const auto ObjCTestValuesForRunOptions =
86     ::testing::ValuesIn(ObjCTestArrayForRunOptions);
87 
88 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportObjCDecl,
89                          ObjCTestValuesForRunOptions);
90