[clang] 8fd3b5d - Fix an edge case in determining is a function has a prototype
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 15 11:04:20 PDT 2022
Author: Aaron Ballman
Date: 2022-04-15T14:04:07-04:00
New Revision: 8fd3b5de3f96300189a2841278e6c7b6654bffc5
URL: https://github.com/llvm/llvm-project/commit/8fd3b5de3f96300189a2841278e6c7b6654bffc5
DIFF: https://github.com/llvm/llvm-project/commit/8fd3b5de3f96300189a2841278e6c7b6654bffc5.diff
LOG: Fix an edge case in determining is a function has a prototype
Given the declaration:
typedef void func_t(unsigned);
__attribute__((noreturn)) func_t func;
we would incorrectly determine that `func` had no prototype because the
`noreturn` attribute would convert the underlying type directly into a
FunctionProtoType, but the declarator for `func` itself was not one for
a function with a prototype. This adds an additional check for when the
declarator is a type representation for a function with a prototype.
Added:
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/test/Sema/warn-strict-prototypes.c
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 76bf67397a6ee..499c70e087898 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8803,15 +8803,21 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
bool isInline = D.getDeclSpec().isInlineSpecified();
if (!SemaRef.getLangOpts().CPlusPlus) {
- // Determine whether the function was written with a
- // prototype. This true when:
+ // Determine whether the function was written with a prototype. This is
+ // true when:
// - there is a prototype in the declarator, or
// - the type R of the function is some kind of typedef or other non-
// attributed reference to a type name (which eventually refers to a
- // function type).
+ // function type). Note, we can't always look at the adjusted type to
+ // check this case because attributes may cause a non-function
+ // declarator to still have a function type. e.g.,
+ // typedef void func(int a);
+ // __attribute__((noreturn)) func other_func; // This has a prototype
bool HasPrototype =
- (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
- (!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
+ (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
+ (D.getDeclSpec().isTypeRep() &&
+ D.getDeclSpec().getRepAsType().get()->isFunctionProtoType()) ||
+ (!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
NewFD = FunctionDecl::Create(
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
diff --git a/clang/test/Sema/warn-strict-prototypes.c b/clang/test/Sema/warn-strict-prototypes.c
index 4dc7913cd33e7..e2cd4dcddc4c0 100644
--- a/clang/test/Sema/warn-strict-prototypes.c
+++ b/clang/test/Sema/warn-strict-prototypes.c
@@ -80,3 +80,13 @@ void foo13(...) __attribute__((overloadable)) {}
void foo14(void) {
foo14_call(); // no-warning
}
+
+// Ensure that redeclarations involving a typedef type work properly, even if
+// there are function attributes involved in the declaration.
+typedef void foo_t(unsigned val);
+__attribute__((noreturn)) foo_t foo15;
+foo_t foo15; // OK
+void foo15(unsigned val); // OK
+
+foo_t foo16;
+void foo16(unsigned val); // OK
More information about the cfe-commits
mailing list