[cfe-commits] r145774 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp lib/Sema/SemaStmt.cpp lib/Sema/TreeTransform.h test/Sema/block-explicit-noreturn-type.c test/Sema/block-return.c test/SemaCXX/instantiate-blocks.cpp

Douglas Gregor dgregor at apple.com
Sat Dec 3 10:08:02 PST 2011


On Dec 3, 2011, at 9:47 AM, Fariborz Jahanian wrote:

> Author: fjahanian
> Date: Sat Dec  3 11:47:53 2011
> New Revision: 145774
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=145774&view=rev
> Log:
> If block literal return type is not specified, return type of the block is 
> inferred from return types. All the return statements have to agree about the type.
> // rdar://10466373
> 
> Added:
>    cfe/trunk/test/Sema/block-explicit-noreturn-type.c
> Modified:
>    cfe/trunk/include/clang/AST/Decl.h
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>    cfe/trunk/lib/Sema/SemaExpr.cpp
>    cfe/trunk/lib/Sema/SemaStmt.cpp
>    cfe/trunk/lib/Sema/TreeTransform.h
>    cfe/trunk/test/Sema/block-return.c
>    cfe/trunk/test/SemaCXX/instantiate-blocks.cpp
> 
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=145774&r1=145773&r2=145774&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Sat Dec  3 11:47:53 2011
> @@ -2981,6 +2981,7 @@
>   // FIXME: This can be packed into the bitfields in Decl.
>   bool IsVariadic : 1;
>   bool CapturesCXXThis : 1;
> +  bool BlockMissingReturnType : 1;
>   /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
>   /// parameters of this function.  This is null if a prototype or if there are
>   /// no formals.
> @@ -2997,6 +2998,7 @@
>   BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
>     : Decl(Block, DC, CaretLoc), DeclContext(Block),
>       IsVariadic(false), CapturesCXXThis(false),
> +      BlockMissingReturnType(true),
>       ParamInfo(0), NumParams(0), Body(0),
>       SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
> 
> @@ -3054,6 +3056,8 @@
>   capture_const_iterator capture_end() const { return Captures + NumCaptures; }
> 
>   bool capturesCXXThis() const { return CapturesCXXThis; }
> +  bool blockMissingReturnType() const { return BlockMissingReturnType; }
> +  void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; }
> 
>   bool capturesVariable(const VarDecl *var) const;
> 
> 
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=145774&r1=145773&r2=145774&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Dec  3 11:47:53 2011
> @@ -4061,6 +4061,9 @@
>   "volatile and restrict|const, volatile, and restrict}5 vs "
>   "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
>   "volatile and restrict|const, volatile, and restrict}6)}4">;
> +def err_typecheck_missing_return_type_incompatible : Error<
> +  "return type %0 must match previous return type %1 when block"
> +  " literal has unspecified explicit return type">;
> 
> def warn_incompatible_qualified_id : Warning<
>   "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
> 
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=145774&r1=145773&r2=145774&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Dec  3 11:47:53 2011
> @@ -8715,8 +8715,10 @@
>   // return type.  TODO:  what should we do with declarators like:
>   //   ^ * { ... }
>   // If the answer is "apply template argument deduction"....
> -  if (RetTy != Context.DependentTy)
> +  if (RetTy != Context.DependentTy) {
>     CurBlock->ReturnType = RetTy;
> +    CurBlock->TheDecl->setBlockMissingReturnType(false);
> +  }
> 
>   // Push block parameters from the declarator if we had them.
>   SmallVector<ParmVarDecl*, 8> Params;
> 
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=145774&r1=145773&r2=145774&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Sat Dec  3 11:47:53 2011
> @@ -1809,6 +1809,16 @@
>   } else if (!RetValExp) {
>     return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));
>   } else if (!RetValExp->isTypeDependent()) {
> +    if (CurBlock->TheDecl->blockMissingReturnType()) {
> +      // when block's return type is not specified, all return types
> +      // must strictly match.
> +      if (Context.getCanonicalType(FnRetType) != 
> +          Context.getCanonicalType(RetValExp->getType())) {

Context.hasSameType(FnRetType, RetValExp->getType()) would be a little cleaner. 

More importantly, I think this is the wrong place for this check, because the code isn't performing function or array lvalue conversions before checking the type of the return expression. I suggest making sure that blocks with inferred return types always go into this code:

  if (CurBlock->ReturnType.isNull()) {
    if (RetValExp) {
      // Don't call UsualUnaryConversions(), since we don't want to do
      // integer promotions here.
      ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
      if (Result.isInvalid())
        return StmtError();
      RetValExp = Result.take();

      if (!RetValExp->isTypeDependent()) {
        CurBlock->ReturnType = RetValExp->getType();
        if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
          // We have to remove a 'const' added to copied-in variable which was
          // part of the implementation spec. and not the actual qualifier for
          // the variable.
          if (CDRE->isConstQualAdded())
            CurBlock->ReturnType.removeLocalConst(); // FIXME: local???
        }
      } else
        CurBlock->ReturnType = Context.DependentTy;
    } else
      CurBlock->ReturnType = Context.VoidTy;
  }

so they all get the same adjustments before checking against previously-deduced return types.

	- Doug

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111203/e28a7ce6/attachment.html>


More information about the cfe-commits mailing list