diff options
| author | John McCall <rjmccall@apple.com> | 2010-06-04 19:02:56 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-06-04 19:02:56 +0000 | 
| commit | 8e346702b6f7d628ad1bf5fc3e8cdc697b08a9b7 (patch) | |
| tree | 1ccc3b8eecb54ecb9db1daf2f2f6c544d618e8a0 | |
| parent | 7f3d95054b492fbf6ebc22f7db32fb1574f25e6c (diff) | |
| download | bcm5719-llvm-8e346702b6f7d628ad1bf5fc3e8cdc697b08a9b7.tar.gz bcm5719-llvm-8e346702b6f7d628ad1bf5fc3e8cdc697b08a9b7.zip  | |
Preserve more information from a block's original function declarator, if one
was given.  Remove some unnecessary accounting from BlockScopeInfo.  Handle
typedef'ed function types until such time as we decide not.
llvm-svn: 105478
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 15 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 84 | ||||
| -rw-r--r-- | clang/test/CodeGen/blocks.c | 6 | 
5 files changed, 74 insertions, 35 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index a3f1b4455e9..43bf21313f6 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3147,7 +3147,7 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,    QualType BlockTy =        Expr->getType()->getAs<BlockPointerType>()->getPointeeType();    // Encode result type. -  getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S); +  getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), S);    // Compute size of all parameters.    // Start with computing size of a pointer in number of bytes.    // FIXME: There might(should) be a better way of doing this computation! diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 32cd6dcc5cb..09d813c7dbe 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -155,9 +155,6 @@ struct FunctionScopeInfo {  /// \brief Retains information about a block that is currently being parsed.  struct BlockScopeInfo : FunctionScopeInfo { -  llvm::SmallVector<ParmVarDecl*, 8> Params; -  bool hasPrototype; -  bool isVariadic;    bool hasBlockDeclRefExprs;    BlockDecl *TheDecl; @@ -166,13 +163,17 @@ struct BlockScopeInfo : FunctionScopeInfo {    /// arguments etc.    Scope *TheScope; -  /// ReturnType - This will get set to block result type, by looking at -  /// return types, if any, in the block body. +  /// ReturnType - The return type of the block, or null if the block +  /// signature didn't provide an explicit return type.    QualType ReturnType; +  /// BlockType - The function type of the block, if one was given. +  /// Its return type may be BuiltinType::Dependent. +  QualType FunctionType; +    BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block) -    : FunctionScopeInfo(NumErrors), hasPrototype(false), isVariadic(false), -      hasBlockDeclRefExprs(false), TheDecl(Block), TheScope(BlockScope) +    : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false), +      TheDecl(Block), TheScope(BlockScope)    {      IsBlockInfo = true;    } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 4f3f41b715f..d47f2ce8edc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -511,7 +511,7 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {    BlockScopeInfo *CurBlock = getCurBlock();    bool isVariadic;    if (CurBlock) -    isVariadic = CurBlock->isVariadic; +    isVariadic = CurBlock->TheDecl->isVariadic();    else if (FunctionDecl *FD = getCurFunctionDecl())      isVariadic = FD->isVariadic();    else diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1640a61a22d..e1a6a04bfd4 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6980,19 +6980,19 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {    QualType T = GetTypeForDeclarator(ParamInfo, CurScope, &Sig);    CurBlock->TheDecl->setSignatureAsWritten(Sig); +  bool isVariadic;    QualType RetTy;    if (const FunctionType *Fn = T->getAs<FunctionType>()) { +    CurBlock->FunctionType = T;      RetTy = Fn->getResultType(); -    CurBlock->hasPrototype = isa<FunctionProtoType>(Fn); -    CurBlock->isVariadic = +    isVariadic =        !isa<FunctionProtoType>(Fn) || cast<FunctionProtoType>(Fn)->isVariadic();    } else {      RetTy = T; -    CurBlock->hasPrototype = true; -    CurBlock->isVariadic = false; +    isVariadic = false;    } -  CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); +  CurBlock->TheDecl->setIsVariadic(isVariadic);    // Don't allow returning an array by value.    if (RetTy->isArrayType()) { @@ -7008,11 +7008,14 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {    }    // Context.DependentTy is used as a placeholder for a missing block -  // return type. +  // return type.  TODO:  what should we do with declarators like: +  //   ^ * { ... } +  // If the answer is "apply template argument deduction"....    if (RetTy != Context.DependentTy)      CurBlock->ReturnType = RetTy;    // Push block parameters from the declarator if we had them. +  llvm::SmallVector<ParmVarDecl*, 8> Params;    if (isa<FunctionProtoType>(T)) {      FunctionProtoTypeLoc TL = cast<FunctionProtoTypeLoc>(Sig->getTypeLoc());      for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { @@ -7022,7 +7025,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {            !Param->isInvalidDecl() &&            !getLangOptions().CPlusPlus)          Diag(Param->getLocation(), diag::err_parameter_name_omitted); -      CurBlock->Params.push_back(Param); +      Params.push_back(Param);      }    // Fake up parameter variables if we have a typedef, like @@ -7034,19 +7037,18 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {          BuildParmVarDeclForTypedef(CurBlock->TheDecl,                                     ParamInfo.getSourceRange().getBegin(),                                     *I); -      CurBlock->Params.push_back(Param); +      Params.push_back(Param);      }    } -  // Set the parmaeters on the block decl. -  if (!CurBlock->Params.empty()) -    CurBlock->TheDecl->setParams(CurBlock->Params.data(), -                                 CurBlock->Params.size()); +  // Set the parameters on the block decl. +  if (!Params.empty()) +    CurBlock->TheDecl->setParams(Params.data(), Params.size());    // Finally we can process decl attributes.    ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); -  if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { +  if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {      Diag(ParamInfo.getAttributes()->getLoc(),           diag::warn_attribute_sentinel_not_variadic) << 1;      // FIXME: remove the attribute. @@ -7054,7 +7056,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {    // Put the parameter variables in scope.  We can bail out immediately    // if we don't have any. -  if (CurBlock->Params.empty()) +  if (Params.empty())      return;    bool ShouldCheckShadow = @@ -7099,22 +7101,52 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,    if (!BSI->ReturnType.isNull())      RetTy = BSI->ReturnType; -  llvm::SmallVector<QualType, 8> ArgTypes; -  for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i) -    ArgTypes.push_back(BSI->Params[i]->getType()); -    bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();    QualType BlockTy; -  if (!BSI->hasPrototype) -    BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0, -                                FunctionType::ExtInfo(NoReturn, 0, CC_Default)); -  else -    BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(), -                                      BSI->isVariadic, 0, false, false, 0, 0, -                                FunctionType::ExtInfo(NoReturn, 0, CC_Default)); + +  // If the user wrote a function type in some form, try to use that. +  if (!BSI->FunctionType.isNull()) { +    const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>(); + +    FunctionType::ExtInfo Ext = FTy->getExtInfo(); +    if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true); +     +    // Turn protoless block types into nullary block types. +    if (isa<FunctionNoProtoType>(FTy)) { +      BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, +                                        false, false, 0, 0, Ext); + +    // Otherwise, if we don't need to change anything about the function type, +    // preserve its sugar structure. +    } else if (FTy->getResultType() == RetTy && +               (!NoReturn || FTy->getNoReturnAttr())) { +      BlockTy = BSI->FunctionType; + +    // Otherwise, make the minimal modifications to the function type. +    } else { +      const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy); +      BlockTy = Context.getFunctionType(RetTy, +                                        FPT->arg_type_begin(), +                                        FPT->getNumArgs(), +                                        FPT->isVariadic(), +                                        /*quals*/ 0, +                                        FPT->hasExceptionSpec(), +                                        FPT->hasAnyExceptionSpec(), +                                        FPT->getNumExceptions(), +                                        FPT->exception_begin(), +                                        Ext); +    } + +  // If we don't have a function type, just build one from nothing. +  } else { +    BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, +                                      false, false, 0, 0, +                             FunctionType::ExtInfo(NoReturn, 0, CC_Default)); +  }    // FIXME: Check that return/parameter types are complete/non-abstract -  DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end()); +  DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), +                           BSI->TheDecl->param_end());    BlockTy = Context.getBlockPointerType(BlockTy);    // If needed, diagnose invalid gotos and switches in the block. diff --git a/clang/test/CodeGen/blocks.c b/clang/test/CodeGen/blocks.c index a0f5dae6f44..6888356a5a1 100644 --- a/clang/test/CodeGen/blocks.c +++ b/clang/test/CodeGen/blocks.c @@ -27,3 +27,9 @@ void (^test1)(void) = ^(void) {    ^ { i = 1; }();  }; +typedef double ftype(double); +// It's not clear that we *should* support this syntax, but until that decision +// is made, we should support it properly and not crash. +ftype ^test2 = ^ftype { +  return 0; +};  | 

