From: Douglas Gregor Date: Mon, 1 Nov 2010 18:37:59 +0000 (+0000) Subject: Require that the types of the parameters of a block literal are complete. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82aa713bcda99f388836c2a30bb868d9c9974817;p=clang Require that the types of the parameters of a block literal are complete. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117942 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index c4d9c0e2c6..88a168927c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1170,7 +1170,8 @@ public: CallExpr *CE, FunctionDecl *FD); /// Helpers for dealing with blocks and functions. - bool CheckParmsForFunctionDef(FunctionDecl *FD); + bool CheckParmsForFunctionDef(ParmVarDecl **Param, ParmVarDecl **ParamEnd, + bool CheckParameterNames); void CheckCXXDefaultArguments(FunctionDecl *FD); void CheckExtraCXXDefaultArguments(Declarator &D); Scope *getNonFieldDeclScope(Scope *S); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 4ed39e2a4b..acd830ddec 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2831,11 +2831,12 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { /// takes care of any checks that cannot be performed on the /// declaration itself, e.g., that the types of each of the function /// parameters are complete. -bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { +bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, + bool CheckParameterNames) { bool HasInvalidParm = false; - for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) { - ParmVarDecl *Param = FD->getParamDecl(p); - + for (; P != PEnd; ++P) { + ParmVarDecl *Param = *P; + // C99 6.7.5.3p4: the parameters in a parameter type list in a // function declarator that is part of a function definition of // that function shall not have incomplete type. @@ -2850,7 +2851,8 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { // C99 6.9.1p5: If the declarator includes a parameter type list, the // declaration of each parameter shall include an identifier. - if (Param->getIdentifier() == 0 && + if (CheckParameterNames && + Param->getIdentifier() == 0 && !Param->isImplicit() && !getLangOptions().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a85e5f5cac..0fb1aa0dda 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3624,7 +3624,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (getLangOptions().CPlusPlus && Param->getType().getUnqualifiedType() != Context.VoidTy) Diag(Param->getLocation(), diag::err_param_typedef_of_void); - // FIXME: Leaks decl? } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = cast(FTI.ArgInfo[i].Param); @@ -4927,10 +4926,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, "Not a function declarator!"); DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; - if (FTI.hasPrototype) { - // FIXME: Diagnose arguments without names in C. - } - Scope *ParentScope = FnBodyScope->getParent(); Decl *DP = HandleDeclarator(ParentScope, D, @@ -5043,7 +5038,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { PushDeclContext(FnBodyScope, FD); // Check the validity of our function parameters - CheckParmsForFunctionDef(FD); + CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(), + /*CheckParameterNames=*/true); bool ShouldCheckShadow = Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored; @@ -7356,7 +7352,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } // Figure out the type that should be used for this enum. - // FIXME: Support -fshort-enums. QualType BestType; unsigned BestWidth; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 17a3aff030..6f6d3714e6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7424,9 +7424,13 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { } // Set the parameters on the block decl. - if (!Params.empty()) + if (!Params.empty()) { CurBlock->TheDecl->setParams(Params.data(), Params.size()); - + CheckParmsForFunctionDef(CurBlock->TheDecl->param_begin(), + CurBlock->TheDecl->param_end(), + /*CheckParameterNames=*/false); + } + // Finally we can process decl attributes. ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); @@ -7464,7 +7468,6 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { // Pop off CurBlock, handle nested blocks. PopDeclContext(); PopFunctionOrBlockScope(); - // FIXME: Delete the ParmVarDecl objects as well??? } /// ActOnBlockStmtExpr - This is called when the body of a block statement @@ -7526,7 +7529,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, FunctionType::ExtInfo(NoReturn, 0, CC_Default)); } - // FIXME: Check that return/parameter types are complete/non-abstract DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), BSI->TheDecl->param_end()); BlockTy = Context.getBlockPointerType(BlockTy); diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm index fd0df4e6e2..559739a48d 100644 --- a/test/SemaObjCXX/blocks.mm +++ b/test/SemaObjCXX/blocks.mm @@ -50,3 +50,27 @@ void foo6(void *block) { void (^vb)(id obj, int idx, BOOL *stop) = (void (^)(id, int, BOOL *))block; BOOL (^bb)(id obj, int idx, BOOL *stop) = (BOOL (^)(id, int, BOOL *))block; } + +// : Require that the types of block +// parameters are complete. +namespace N1 { + template class ptr; // expected-note{{template is declared here}} + + template + class foo { + public: + void bar(void (^)(ptr<_T>)); + }; + + class X; + + void test2(); + + void test() + { + foo f; + f.bar(^(ptr _f) { // expected-error{{implicit instantiation of undefined template 'N1::ptr'}} + test2(); + }); + } +}