Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / unittests / AST / AttrTest.cpp
blob46c3f5729021ec5cd328d1116b306254baf54ec4
1 //===- unittests/AST/AttrTests.cpp --- Attribute 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 //===----------------------------------------------------------------------===//
9 #include "clang/AST/Attr.h"
10 #include "clang/ASTMatchers/ASTMatchFinder.h"
11 #include "clang/ASTMatchers/ASTMatchers.h"
12 #include "clang/Basic/AttrKinds.h"
13 #include "clang/Tooling/Tooling.h"
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
17 using namespace clang;
19 namespace {
21 using clang::ast_matchers::constantExpr;
22 using clang::ast_matchers::equals;
23 using clang::ast_matchers::functionDecl;
24 using clang::ast_matchers::has;
25 using clang::ast_matchers::hasDescendant;
26 using clang::ast_matchers::hasName;
27 using clang::ast_matchers::integerLiteral;
28 using clang::ast_matchers::match;
29 using clang::ast_matchers::selectFirst;
30 using clang::ast_matchers::stringLiteral;
31 using clang::ast_matchers::varDecl;
32 using clang::tooling::buildASTFromCode;
33 using clang::tooling::buildASTFromCodeWithArgs;
35 TEST(Attr, Doc) {
36 EXPECT_THAT(Attr::getDocumentation(attr::Used).str(),
37 testing::HasSubstr("The compiler must emit the definition even "
38 "if it appears to be unused"));
41 const FunctionDecl *getFunctionNode(ASTUnit *AST, const std::string &Name) {
42 auto Result =
43 match(functionDecl(hasName(Name)).bind("fn"), AST->getASTContext());
44 EXPECT_EQ(Result.size(), 1u);
45 return Result[0].getNodeAs<FunctionDecl>("fn");
48 const VarDecl *getVariableNode(ASTUnit *AST, const std::string &Name) {
49 auto Result = match(varDecl(hasName(Name)).bind("var"), AST->getASTContext());
50 EXPECT_EQ(Result.size(), 1u);
51 return Result[0].getNodeAs<VarDecl>("var");
54 template <class ModifiedTypeLoc>
55 void AssertAnnotatedAs(TypeLoc TL, llvm::StringRef annotation,
56 ModifiedTypeLoc &ModifiedTL,
57 const AnnotateTypeAttr **AnnotateOut = nullptr) {
58 const auto AttributedTL = TL.getAs<AttributedTypeLoc>();
59 ASSERT_FALSE(AttributedTL.isNull());
60 ModifiedTL = AttributedTL.getModifiedLoc().getAs<ModifiedTypeLoc>();
61 ASSERT_TRUE(ModifiedTL);
63 ASSERT_NE(AttributedTL.getAttr(), nullptr);
64 const auto *Annotate = dyn_cast<AnnotateTypeAttr>(AttributedTL.getAttr());
65 ASSERT_NE(Annotate, nullptr);
66 EXPECT_EQ(Annotate->getAnnotation(), annotation);
67 if (AnnotateOut) {
68 *AnnotateOut = Annotate;
72 TEST(Attr, AnnotateType) {
74 // Test that the AnnotateType attribute shows up in the right places and that
75 // it stores its arguments correctly.
77 auto AST = buildASTFromCode(R"cpp(
78 void f(int* [[clang::annotate_type("foo", "arg1", 2)]] *,
79 int [[clang::annotate_type("bar")]]);
81 int [[clang::annotate_type("int")]] * [[clang::annotate_type("ptr")]]
82 array[10] [[clang::annotate_type("arr")]];
84 void (* [[clang::annotate_type("funcptr")]] fp)(void);
86 struct S { int mem; };
87 int [[clang::annotate_type("int")]]
88 S::* [[clang::annotate_type("ptr_to_mem")]] ptr_to_member = &S::mem;
89 )cpp");
92 const FunctionDecl *Func = getFunctionNode(AST.get(), "f");
94 // First parameter.
95 const auto PointerTL = Func->getParamDecl(0)
96 ->getTypeSourceInfo()
97 ->getTypeLoc()
98 .getAs<PointerTypeLoc>();
99 ASSERT_FALSE(PointerTL.isNull());
100 PointerTypeLoc PointerPointerTL;
101 const AnnotateTypeAttr *Annotate;
102 AssertAnnotatedAs(PointerTL.getPointeeLoc(), "foo", PointerPointerTL,
103 &Annotate);
105 EXPECT_EQ(Annotate->args_size(), 2u);
106 const auto *StringLit = selectFirst<StringLiteral>(
107 "str", match(constantExpr(hasDescendant(stringLiteral().bind("str"))),
108 *Annotate->args_begin()[0], AST->getASTContext()));
109 ASSERT_NE(StringLit, nullptr);
110 EXPECT_EQ(StringLit->getString(), "arg1");
111 EXPECT_EQ(match(constantExpr(has(integerLiteral(equals(2u)).bind("int"))),
112 *Annotate->args_begin()[1], AST->getASTContext())
113 .size(),
114 1u);
116 // Second parameter.
117 BuiltinTypeLoc IntTL;
118 AssertAnnotatedAs(Func->getParamDecl(1)->getTypeSourceInfo()->getTypeLoc(),
119 "bar", IntTL);
120 EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy);
124 const VarDecl *Var = getVariableNode(AST.get(), "array");
126 ArrayTypeLoc ArrayTL;
127 AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "arr", ArrayTL);
128 PointerTypeLoc PointerTL;
129 AssertAnnotatedAs(ArrayTL.getElementLoc(), "ptr", PointerTL);
130 BuiltinTypeLoc IntTL;
131 AssertAnnotatedAs(PointerTL.getPointeeLoc(), "int", IntTL);
132 EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy);
136 const VarDecl *Var = getVariableNode(AST.get(), "fp");
138 PointerTypeLoc PointerTL;
139 AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "funcptr",
140 PointerTL);
141 ASSERT_TRUE(
142 PointerTL.getPointeeLoc().IgnoreParens().getAs<FunctionTypeLoc>());
146 const VarDecl *Var = getVariableNode(AST.get(), "ptr_to_member");
148 MemberPointerTypeLoc MemberPointerTL;
149 AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "ptr_to_mem",
150 MemberPointerTL);
151 BuiltinTypeLoc IntTL;
152 AssertAnnotatedAs(MemberPointerTL.getPointeeLoc(), "int", IntTL);
153 EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy);
156 // Test type annotation on an `__auto_type` type in C mode.
157 AST = buildASTFromCodeWithArgs(R"c(
158 __auto_type [[clang::annotate_type("auto")]] auto_var = 1;
159 )c",
161 "input.c");
164 const VarDecl *Var = getVariableNode(AST.get(), "auto_var");
166 AutoTypeLoc AutoTL;
167 AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "auto", AutoTL);
171 TEST(Attr, RegularKeywordAttribute) {
172 auto AST = clang::tooling::buildASTFromCode("");
173 auto &Ctx = AST->getASTContext();
174 auto Funcref = clang::WebAssemblyFuncrefAttr::CreateImplicit(Ctx);
175 EXPECT_EQ(Funcref->getSyntax(), clang::AttributeCommonInfo::AS_Keyword);
176 ASSERT_FALSE(Funcref->isRegularKeywordAttribute());
178 auto Streaming = clang::ArmStreamingAttr::CreateImplicit(Ctx);
179 EXPECT_EQ(Streaming->getSyntax(), clang::AttributeCommonInfo::AS_Keyword);
180 ASSERT_TRUE(Streaming->isRegularKeywordAttribute());
183 } // namespace