-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Reapply 19c708c "FunctionDecl::getFunctionTypeLoc: ignore function type attributes (#118420)" #136484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…pe attributes (llvm#118420)" Avoid using PreservesMost in the testcase as it is not supported on all targets. Original PR llvm#118290. --------- Co-authored-by: v01dxyz <v01dxyz@v01d.xyz> Co-authored-by: Owen Anderson <resistor@mac.com>
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-tools-extra Author: Owen Anderson (resistor) ChangesAvoid using PreservesMost in the testcase as it is not supported on all targets. Original PR #118290. Full diff: https://github.com/llvm/llvm-project/pull/136484.diff 3 Files Affected:
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 77d78b8777fe3..030e499577706 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -1577,19 +1577,21 @@ TEST(TypeHints, Aliased) {
}
TEST(TypeHints, CallingConvention) {
- // Check that we don't crash for lambdas without a FunctionTypeLoc
+ // Check that we don't crash for lambdas with an annotation
// https://github.com/clangd/clangd/issues/2223
- std::string Code = R"cpp(
+ Annotations Source(R"cpp(
void test() {
- []() __cdecl {};
+ []($lambda[[)]]__cdecl {};
}
- )cpp";
- TestTU TU = TestTU::withCode(Code);
+ )cpp");
+ TestTU TU = TestTU::withCode(Source.code());
TU.ExtraArgs.push_back("--target=x86_64-w64-mingw32");
TU.PredefineMacros = true; // for the __cdecl
auto AST = TU.build();
- EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
+ EXPECT_THAT(
+ hintsOfKind(AST, InlayHintKind::Type),
+ ElementsAre(HintMatcher(ExpectedHint{"-> void", "lambda"}, Source)));
}
TEST(TypeHints, Decltype) {
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ad1cb01592e9b..1d9208f0e1c72 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3910,8 +3910,25 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const {
const TypeSourceInfo *TSI = getTypeSourceInfo();
- return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>()
- : FunctionTypeLoc();
+
+ if (!TSI)
+ return FunctionTypeLoc();
+
+ TypeLoc TL = TSI->getTypeLoc();
+ FunctionTypeLoc FTL;
+
+ while (!(FTL = TL.getAs<FunctionTypeLoc>())) {
+ if (const auto PTL = TL.getAs<ParenTypeLoc>())
+ TL = PTL.getInnerLoc();
+ else if (const auto ATL = TL.getAs<AttributedTypeLoc>())
+ TL = ATL.getEquivalentTypeLoc();
+ else if (const auto MQTL = TL.getAs<MacroQualifiedTypeLoc>())
+ TL = MQTL.getInnerLoc();
+ else
+ break;
+ }
+
+ return FTL;
}
SourceRange FunctionDecl::getReturnTypeSourceRange() const {
diff --git a/clang/unittests/AST/AttrTest.cpp b/clang/unittests/AST/AttrTest.cpp
index 46c3f5729021e..bbf1c0f9a382b 100644
--- a/clang/unittests/AST/AttrTest.cpp
+++ b/clang/unittests/AST/AttrTest.cpp
@@ -86,6 +86,22 @@ TEST(Attr, AnnotateType) {
struct S { int mem; };
int [[clang::annotate_type("int")]]
S::* [[clang::annotate_type("ptr_to_mem")]] ptr_to_member = &S::mem;
+
+ // Function Type Attributes
+ __attribute__((noreturn)) int f_noreturn();
+
+ #define NO_RETURN __attribute__((noreturn))
+ NO_RETURN int f_macro_attribue();
+
+ int (__attribute__((noreturn)) f_paren_attribute)();
+
+ int (
+ NO_RETURN
+ (
+ __attribute__((warn_unused_result))
+ (f_w_paren_and_attr)
+ )
+ ) ();
)cpp");
{
@@ -153,6 +169,59 @@ TEST(Attr, AnnotateType) {
EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy);
}
+ {
+ const FunctionDecl *Func = getFunctionNode(AST.get(), "f_noreturn");
+ const FunctionTypeLoc FTL = Func->getFunctionTypeLoc();
+ const FunctionType *FT = FTL.getTypePtr();
+
+ EXPECT_TRUE(FT->getNoReturnAttr());
+ }
+
+ {
+ for (auto should_have_func_type_loc : {
+ "f_macro_attribue",
+ "f_paren_attribute",
+ "f_w_paren_and_attr",
+ }) {
+ llvm::errs() << "O: " << should_have_func_type_loc << "\n";
+ const FunctionDecl *Func =
+ getFunctionNode(AST.get(), should_have_func_type_loc);
+
+ EXPECT_TRUE(Func->getFunctionTypeLoc());
+ }
+ }
+
+ // The following test verifies getFunctionTypeLoc returns a type
+ // which takes into account the attribute (instead of only the nake
+ // type).
+ //
+ // This is hard to do with C/C++ because it seems using a function
+ // type attribute with a C/C++ function declaration only results
+ // with either:
+ //
+ // 1. It does NOT produce any AttributedType (for example it only
+ // sets one flag of the FunctionType's ExtInfo, e.g. NoReturn).
+ // 2. It produces an AttributedType with modified type and
+ // equivalent type that are equal (for example, that's what
+ // happens with Calling Convention attributes).
+ //
+ // Fortunately, ObjC has one specific function type attribute that
+ // creates an AttributedType with different modified type and
+ // equivalent type.
+ auto AST_ObjC = buildASTFromCodeWithArgs(
+ R"objc(
+ __attribute__((ns_returns_retained)) id f();
+ )objc",
+ {"-fobjc-arc", "-fsyntax-only", "-fobjc-runtime=macosx-10.7"},
+ "input.mm");
+ {
+ const FunctionDecl *f = getFunctionNode(AST_ObjC.get(), "f");
+ const FunctionTypeLoc FTL = f->getFunctionTypeLoc();
+
+ const FunctionType *FT = FTL.getTypePtr();
+ EXPECT_TRUE(FT->getExtInfo().getProducesResult());
+ }
+
// Test type annotation on an `__auto_type` type in C mode.
AST = buildASTFromCodeWithArgs(R"c(
__auto_type [[clang::annotate_type("auto")]] auto_var = 1;
|
|
Avoid using PreservesMost in the testcase as it is not supported on all targets.
Original PR #118290.