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