@@ -86,6 +86,23 @@ TEST(Attr, AnnotateType) {
86
86
struct S { int mem; };
87
87
int [[clang::annotate_type("int")]]
88
88
S::* [[clang::annotate_type("ptr_to_mem")]] ptr_to_member = &S::mem;
89
+
90
+ // Function Type Attributes
91
+ __attribute__((noreturn)) int f_noreturn();
92
+ __attribute__((preserve_most)) int f_cc_preserve_most();
93
+
94
+ #define PRESERVE_MOST __attribute__((preserve_most))
95
+ PRESERVE_MOST int f_macro_attribue();
96
+
97
+ int (__attribute__((preserve_most)) f_paren_attribute)();
98
+
99
+ int (
100
+ PRESERVE_MOST
101
+ (
102
+ __attribute__((warn_unused_result))
103
+ (f_w_paren_and_attr)
104
+ )
105
+ ) ();
89
106
)cpp" );
90
107
91
108
{
@@ -153,6 +170,67 @@ TEST(Attr, AnnotateType) {
153
170
EXPECT_EQ (IntTL.getType (), AST->getASTContext ().IntTy );
154
171
}
155
172
173
+ {
174
+ const FunctionDecl *Func = getFunctionNode (AST.get (), " f_noreturn" );
175
+ const FunctionTypeLoc FTL = Func->getFunctionTypeLoc ();
176
+ const FunctionType *FT = FTL.getTypePtr ();
177
+
178
+ EXPECT_TRUE (FT->getNoReturnAttr ());
179
+ }
180
+
181
+ {
182
+ const FunctionDecl *Func = getFunctionNode (AST.get (), " f_cc_preserve_most" );
183
+ const FunctionTypeLoc FTL = Func->getFunctionTypeLoc ();
184
+ const FunctionType *FT = FTL.getTypePtr ();
185
+
186
+ EXPECT_TRUE (FT->getCallConv () == CC_PreserveMost);
187
+ }
188
+
189
+ {
190
+ for (auto should_have_func_type_loc : {
191
+ " f_macro_attribue" ,
192
+ " f_paren_attribute" ,
193
+ " f_w_paren_and_attr" ,
194
+ }) {
195
+ llvm::errs () << " O: " << should_have_func_type_loc << " \n " ;
196
+ const FunctionDecl *Func =
197
+ getFunctionNode (AST.get (), should_have_func_type_loc);
198
+
199
+ EXPECT_TRUE (Func->getFunctionTypeLoc ());
200
+ }
201
+ }
202
+
203
+ // The following test verifies getFunctionTypeLoc returns a type
204
+ // which takes into account the attribute (instead of only the nake
205
+ // type).
206
+ //
207
+ // This is hard to do with C/C++ because it seems using a function
208
+ // type attribute with a C/C++ function declaration only results
209
+ // with either:
210
+ //
211
+ // 1. It does NOT produce any AttributedType (for example it only
212
+ // sets one flag of the FunctionType's ExtInfo, e.g. NoReturn).
213
+ // 2. It produces an AttributedType with modified type and
214
+ // equivalent type that are equal (for example, that's what
215
+ // happens with Calling Convention attributes).
216
+ //
217
+ // Fortunately, ObjC has one specific function type attribute that
218
+ // creates an AttributedType with different modified type and
219
+ // equivalent type.
220
+ auto AST_ObjC = buildASTFromCodeWithArgs (
221
+ R"objc(
222
+ __attribute__((ns_returns_retained)) id f();
223
+ )objc" ,
224
+ {" -fobjc-arc" , " -fsyntax-only" , " -fobjc-runtime=macosx-10.7" },
225
+ " input.mm" );
226
+ {
227
+ const FunctionDecl *f = getFunctionNode (AST_ObjC.get (), " f" );
228
+ const FunctionTypeLoc FTL = f->getFunctionTypeLoc ();
229
+
230
+ const FunctionType *FT = FTL.getTypePtr ();
231
+ EXPECT_TRUE (FT->getExtInfo ().getProducesResult ());
232
+ }
233
+
156
234
// Test type annotation on an `__auto_type` type in C mode.
157
235
AST = buildASTFromCodeWithArgs (R"c(
158
236
__auto_type [[clang::annotate_type("auto")]] auto_var = 1;
0 commit comments