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