1 //===- unittests/AST/DeclTest.cpp --- Declaration tests -------------------===//
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 // Unit tests for Decl nodes in the AST.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/Mangle.h"
15 #include "clang/ASTMatchers/ASTMatchFinder.h"
16 #include "clang/Basic/LLVM.h"
17 #include "clang/Tooling/Tooling.h"
18 #include "gtest/gtest.h"
19 
20 using namespace clang::ast_matchers;
21 using namespace clang::tooling;
22 using namespace clang;
23 
24 TEST(Decl, CleansUpAPValues) {
25   MatchFinder Finder;
26   std::unique_ptr<FrontendActionFactory> Factory(
27       newFrontendActionFactory(&Finder));
28 
29   // This is a regression test for a memory leak in APValues for structs that
30   // allocate memory. This test only fails if run under valgrind with full leak
31   // checking enabled.
32   std::vector<std::string> Args(1, "-std=c++11");
33   Args.push_back("-fno-ms-extensions");
34   ASSERT_TRUE(runToolOnCodeWithArgs(
35       Factory->create(),
36       "struct X { int a; }; constexpr X x = { 42 };"
37       "union Y { constexpr Y(int a) : a(a) {} int a; }; constexpr Y y = { 42 };"
38       "constexpr int z[2] = { 42, 43 };"
39       "constexpr int __attribute__((vector_size(16))) v1 = {};"
40       "\n#ifdef __SIZEOF_INT128__\n"
41       "constexpr __uint128_t large_int = 0xffffffffffffffff;"
42       "constexpr __uint128_t small_int = 1;"
43       "\n#endif\n"
44       "constexpr double d1 = 42.42;"
45       "constexpr long double d2 = 42.42;"
46       "constexpr _Complex long double c1 = 42.0i;"
47       "constexpr _Complex long double c2 = 42.0;"
48       "template<int N> struct A : A<N-1> {};"
49       "template<> struct A<0> { int n; }; A<50> a;"
50       "constexpr int &r = a.n;"
51       "constexpr int A<50>::*p = &A<50>::n;"
52       "void f() { foo: bar: constexpr int k = __builtin_constant_p(0) ?"
53       "                         (char*)&&foo - (char*)&&bar : 0; }",
54       Args));
55 
56   // FIXME: Once this test starts breaking we can test APValue::needsCleanup
57   // for ComplexInt.
58   ASSERT_FALSE(runToolOnCodeWithArgs(
59       Factory->create(),
60       "constexpr _Complex __uint128_t c = 0xffffffffffffffff;",
61       Args));
62 }
63 
64 TEST(Decl, AsmLabelAttr) {
65   // Create two method decls: `f` and `g`.
66   StringRef Code = R"(
67     struct S {
68       void f() {}
69       void g() {}
70     };
71   )";
72   auto AST =
73       tooling::buildASTFromCodeWithArgs(Code, {"-target", "i386-apple-darwin"});
74   ASTContext &Ctx = AST->getASTContext();
75   assert(Ctx.getTargetInfo().getDataLayout().getGlobalPrefix() &&
76          "Expected target to have a global prefix");
77   DiagnosticsEngine &Diags = AST->getDiagnostics();
78   SourceManager &SM = AST->getSourceManager();
79   FileID MainFileID = SM.getMainFileID();
80 
81   // Find the method decls within the AST.
82   SmallVector<Decl *, 1> Decls;
83   AST->findFileRegionDecls(MainFileID, Code.find('{'), 0, Decls);
84   ASSERT_TRUE(Decls.size() == 1);
85   CXXRecordDecl *DeclS = cast<CXXRecordDecl>(Decls[0]);
86   NamedDecl *DeclF = *DeclS->method_begin();
87   NamedDecl *DeclG = *(++DeclS->method_begin());
88 
89   // Attach asm labels to the decls: one literal, and one not.
90   DeclF->addAttr(::new (Ctx) AsmLabelAttr(Ctx, SourceLocation(), "foo",
91                                           /*LiteralLabel=*/true));
92   DeclG->addAttr(::new (Ctx) AsmLabelAttr(Ctx, SourceLocation(), "goo",
93                                           /*LiteralLabel=*/false));
94 
95   // Mangle the decl names.
96   std::string MangleF, MangleG;
97   std::unique_ptr<ItaniumMangleContext> MC(
98       ItaniumMangleContext::create(Ctx, Diags));
99   {
100     llvm::raw_string_ostream OS_F(MangleF);
101     llvm::raw_string_ostream OS_G(MangleG);
102     MC->mangleName(DeclF, OS_F);
103     MC->mangleName(DeclG, OS_G);
104   }
105 
106   ASSERT_TRUE(0 == MangleF.compare("\x01" "foo"));
107   ASSERT_TRUE(0 == MangleG.compare("goo"));
108 }
109