Skip to content

Commit

Permalink
[Sema] Improve -Wstrict-prototypes diagnostic message for blocks.
Browse files Browse the repository at this point in the history
Print "this block declaration is not a prototype" for non-prototype
declarations of blocks instead of "this function declaration ...".

rdar://problem/32461723

Differential Revision: https://reviews.llvm.org/D33739

llvm-svn: 304507
  • Loading branch information
ahatanaka committed Jun 2, 2017
1 parent 4b46f72 commit 13b3331
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 18 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -4584,7 +4584,7 @@ def warn_missing_prototype : Warning<
def note_declaration_not_a_prototype : Note<
"this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">;
def warn_strict_prototypes : Warning<
"this %select{function declaration is not|"
"this %select{function declaration is not|block declaration is not|"
"old-style function definition is not preceded by}0 a prototype">,
InGroup<DiagGroup<"strict-prototypes">>, DefaultIgnore;
def warn_missing_variable_declarations : Warning<
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12309,7 +12309,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
TypeSourceInfo *TI = FD->getTypeSourceInfo();
TypeLoc TL = TI->getTypeLoc();
FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>();
Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1;
Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2;
}
}

Expand Down
43 changes: 30 additions & 13 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4347,19 +4347,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);

// GNU warning -Wstrict-prototypes
// Warn if a function declaration is without a prototype.
// This warning is issued for all kinds of unprototyped function
// declarations (i.e. function type typedef, function pointer etc.)
// C99 6.7.5.3p14:
// The empty list in a function declarator that is not part of a
// definition of that function specifies that no information
// about the number or types of the parameters is supplied.
if (D.getFunctionDefinitionKind() == FDK_Declaration &&
FTI.NumParams == 0 && !LangOpts.CPlusPlus)
S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
<< 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");

FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));

if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) {
Expand Down Expand Up @@ -4602,6 +4589,36 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
const_cast<AttributeList *>(DeclType.getAttrs()));
}

// GNU warning -Wstrict-prototypes
// Warn if a function declaration is without a prototype.
// This warning is issued for all kinds of unprototyped function
// declarations (i.e. function type typedef, function pointer etc.)
// C99 6.7.5.3p14:
// The empty list in a function declarator that is not part of a definition
// of that function specifies that no information about the number or types
// of the parameters is supplied.
if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) {
bool IsBlock = false;
for (const DeclaratorChunk &DeclType : D.type_objects()) {
switch (DeclType.Kind) {
case DeclaratorChunk::BlockPointer:
IsBlock = true;
break;
case DeclaratorChunk::Function: {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
if (FTI.NumParams == 0)
S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
<< IsBlock
<< FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
IsBlock = false;
break;
}
default:
break;
}
}
}

assert(!T.isNull() && "T must not be null after this point");

if (LangOpts.CPlusPlus && T->isFunctionType()) {
Expand Down
11 changes: 8 additions & 3 deletions clang/test/Sema/warn-strict-prototypes.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@

@interface Foo

@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this function declaration is not a prototype}}
@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this block declaration is not a prototype}}
@property (nonatomic, copy) void (^block)(void); // no warning

- doStuff:(void (^)()) completionHandler; // expected-warning {{this function declaration is not a prototype}}
- doStuff:(void (^)()) completionHandler; // expected-warning {{this block declaration is not a prototype}}
- doOtherStuff:(void (^)(void)) completionHandler; // no warning

@end

void foo() {
void (^block)() = // expected-warning {{this function declaration is not a prototype}}
void (^block)() = // expected-warning {{this block declaration is not a prototype}}
^void(int arg) { // no warning
};
void (^block2)(void) = ^void() { // no warning
};
void (^block3)(void) = ^ { // no warning
};
}

void (*(^(*(^block4)()) // expected-warning {{this block declaration is not a prototype}}
()) // expected-warning {{this function declaration is not a prototype}}
()) // expected-warning {{this block declaration is not a prototype}}
(); // expected-warning {{this function declaration is not a prototype}}

0 comments on commit 13b3331

Please sign in to comment.