Skip to content

Commit aa3f35f

Browse files
resistorv01dXYZv01dxyz
authored andcommitted
Reapply 19c708c "FunctionDecl::getFunctionTypeLoc: ignore function type attributes (llvm#118420)" (llvm#136484)
Avoid using PreservesMost in the testcase as it is not supported on all targets. Original PR llvm#118290. Co-authored-by: Robert Dazi <[email protected]> Co-authored-by: v01dxyz <[email protected]>
1 parent f413be1 commit aa3f35f

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

clang-tools-extra/clangd/unittests/InlayHintTests.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,19 +1577,21 @@ TEST(TypeHints, Aliased) {
15771577
}
15781578

15791579
TEST(TypeHints, CallingConvention) {
1580-
// Check that we don't crash for lambdas without a FunctionTypeLoc
1580+
// Check that we don't crash for lambdas with an annotation
15811581
// https://github.com/clangd/clangd/issues/2223
1582-
std::string Code = R"cpp(
1582+
Annotations Source(R"cpp(
15831583
void test() {
1584-
[]() __cdecl {};
1584+
[]($lambda[[)]]__cdecl {};
15851585
}
1586-
)cpp";
1587-
TestTU TU = TestTU::withCode(Code);
1586+
)cpp");
1587+
TestTU TU = TestTU::withCode(Source.code());
15881588
TU.ExtraArgs.push_back("--target=x86_64-w64-mingw32");
15891589
TU.PredefineMacros = true; // for the __cdecl
15901590
auto AST = TU.build();
15911591

1592-
EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
1592+
EXPECT_THAT(
1593+
hintsOfKind(AST, InlayHintKind::Type),
1594+
ElementsAre(HintMatcher(ExpectedHint{"-> void", "lambda"}, Source)));
15931595
}
15941596

15951597
TEST(TypeHints, Decltype) {

clang/lib/AST/Decl.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3910,8 +3910,25 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
39103910

39113911
FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const {
39123912
const TypeSourceInfo *TSI = getTypeSourceInfo();
3913-
return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>()
3914-
: FunctionTypeLoc();
3913+
3914+
if (!TSI)
3915+
return FunctionTypeLoc();
3916+
3917+
TypeLoc TL = TSI->getTypeLoc();
3918+
FunctionTypeLoc FTL;
3919+
3920+
while (!(FTL = TL.getAs<FunctionTypeLoc>())) {
3921+
if (const auto PTL = TL.getAs<ParenTypeLoc>())
3922+
TL = PTL.getInnerLoc();
3923+
else if (const auto ATL = TL.getAs<AttributedTypeLoc>())
3924+
TL = ATL.getEquivalentTypeLoc();
3925+
else if (const auto MQTL = TL.getAs<MacroQualifiedTypeLoc>())
3926+
TL = MQTL.getInnerLoc();
3927+
else
3928+
break;
3929+
}
3930+
3931+
return FTL;
39153932
}
39163933

39173934
SourceRange FunctionDecl::getReturnTypeSourceRange() const {

clang/unittests/AST/AttrTest.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)