Skip to content

Commit 8fd3b5d

Browse files
committed
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.
1 parent 2f78f94 commit 8fd3b5d

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8803,15 +8803,21 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
88038803
bool isInline = D.getDeclSpec().isInlineSpecified();
88048804

88058805
if (!SemaRef.getLangOpts().CPlusPlus) {
8806-
// Determine whether the function was written with a
8807-
// prototype. This true when:
8806+
// Determine whether the function was written with a prototype. This is
8807+
// true when:
88088808
// - there is a prototype in the declarator, or
88098809
// - the type R of the function is some kind of typedef or other non-
88108810
// attributed reference to a type name (which eventually refers to a
8811-
// function type).
8811+
// function type). Note, we can't always look at the adjusted type to
8812+
// check this case because attributes may cause a non-function
8813+
// declarator to still have a function type. e.g.,
8814+
// typedef void func(int a);
8815+
// __attribute__((noreturn)) func other_func; // This has a prototype
88128816
bool HasPrototype =
8813-
(D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
8814-
(!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
8817+
(D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
8818+
(D.getDeclSpec().isTypeRep() &&
8819+
D.getDeclSpec().getRepAsType().get()->isFunctionProtoType()) ||
8820+
(!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
88158821

88168822
NewFD = FunctionDecl::Create(
88178823
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,

clang/test/Sema/warn-strict-prototypes.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,13 @@ void foo13(...) __attribute__((overloadable)) {}
8080
void foo14(void) {
8181
foo14_call(); // no-warning
8282
}
83+
84+
// Ensure that redeclarations involving a typedef type work properly, even if
85+
// there are function attributes involved in the declaration.
86+
typedef void foo_t(unsigned val);
87+
__attribute__((noreturn)) foo_t foo15;
88+
foo_t foo15; // OK
89+
void foo15(unsigned val); // OK
90+
91+
foo_t foo16;
92+
void foo16(unsigned val); // OK

0 commit comments

Comments
 (0)