diff options
| author | John McCall <rjmccall@apple.com> | 2010-06-04 11:21:44 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-06-04 11:21:44 +0000 | 
| commit | a3ccba0417f909fd7292af0e9e788e924046d85c (patch) | |
| tree | 2a4baa247ce2652b53c610890dddc7496f5b3ee2 | |
| parent | 52d6350dd202a521050164afb75ceadccbe9a084 (diff) | |
| download | bcm5719-llvm-a3ccba0417f909fd7292af0e9e788e924046d85c.tar.gz bcm5719-llvm-a3ccba0417f909fd7292af0e9e788e924046d85c.zip | |
Restructure how we interpret block-literal declarators.  Correctly handle
the case where we pick up block arguments from a typedef.  Save the block
signature as it was written, and preserve same through PCH.
llvm-svn: 105466
| -rw-r--r-- | clang/include/clang/AST/Decl.h | 7 | ||||
| -rw-r--r-- | clang/lib/Frontend/PCHReaderDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Frontend/PCHWriterDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 134 | 
6 files changed, 88 insertions, 80 deletions
| diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 61447295cee..1e507a5d25e 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2127,11 +2127,13 @@ class BlockDecl : public Decl, public DeclContext {    unsigned NumParams;    Stmt *Body; +  TypeSourceInfo *SignatureAsWritten;  protected:    BlockDecl(DeclContext *DC, SourceLocation CaretLoc)      : Decl(Block, DC, CaretLoc), DeclContext(Block), -      IsVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} +      IsVariadic(false), ParamInfo(0), NumParams(0), Body(0), +      SignatureAsWritten(0) {}    virtual ~BlockDecl();    virtual void Destroy(ASTContext& C); @@ -2148,6 +2150,9 @@ public:    Stmt *getBody() const { return (Stmt*) Body; }    void setBody(CompoundStmt *B) { Body = (Stmt*) B; } +  void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; } +  TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; } +    // Iterator access to formal parameters.    unsigned param_size() const { return getNumParams(); }    typedef ParmVarDecl **param_iterator; diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 606e852385d..8b7b66c2b85 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -462,6 +462,7 @@ void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {  void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {    VisitDecl(BD);    BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadDeclStmt())); +  BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Record, Idx));    unsigned NumParams = Record[Idx++];    llvm::SmallVector<ParmVarDecl *, 16> Params;    Params.reserve(NumParams); diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index d0a01f083f9..8eeef7c741e 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/lib/Frontend/PCHWriterDecl.cpp @@ -471,6 +471,7 @@ void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {  void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {    VisitDecl(D);    Writer.AddStmt(D->getBody()); +  Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record);    Record.push_back(D->param_size());    for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();         P != PEnd; ++P) diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index e4e63c330b2..32cd6dcc5cb 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -841,6 +841,9 @@ public:                                  bool &OverloadableAttrRequired);    void CheckMain(FunctionDecl *FD);    virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D); +  ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, +                                          SourceLocation Loc, +                                          QualType T);    ParmVarDecl *CheckParameter(DeclContext *DC,                                TypeSourceInfo *TSInfo, QualType T,                                IdentifierInfo *Name, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 02a157f1d85..52e4bb9aca3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3272,14 +3272,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,      // Synthesize a parameter for each argument type.      for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),           AE = FT->arg_type_end(); AI != AE; ++AI) { -      ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD, -                                               D.getIdentifierLoc(), 0, -                                               *AI,  -                                         Context.getTrivialTypeSourceInfo(*AI,  -                                                          D.getIdentifierLoc()), -                                               VarDecl::None, -                                               VarDecl::None, 0); -      Param->setImplicit(); +      ParmVarDecl *Param = +        BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);        Params.push_back(Param);      }    } else { @@ -4331,6 +4325,18 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {    return DeclPtrTy::make(New);  } +/// \brief Synthesizes a variable for a parameter arising from a +/// typedef. +ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, +                                              SourceLocation Loc, +                                              QualType T) { +  ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0, +                                T, Context.getTrivialTypeSourceInfo(T, Loc), +                                           VarDecl::None, VarDecl::None, 0); +  Param->setImplicit(); +  return Param; +} +  ParmVarDecl *Sema::CheckParameter(DeclContext *DC,                                     TypeSourceInfo *TSInfo, QualType T,                                    IdentifierInfo *Name, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 906fd08828d..1640a61a22d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6976,62 +6976,47 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {    assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");    BlockScopeInfo *CurBlock = getCurBlock(); -  if (ParamInfo.getNumTypeObjects() == 0 -      || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) { -    ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); -    QualType T = GetTypeForDeclarator(ParamInfo, CurScope); - -    if (T->isArrayType()) { -      Diag(ParamInfo.getSourceRange().getBegin(), -           diag::err_block_returns_array); -      return; -    } - -    // The parameter list is optional, if there was none, assume (). -    if (!T->isFunctionType()) -      T = Context.getFunctionType(T, 0, 0, false, 0, false, false, 0, 0, -                                  FunctionType::ExtInfo()); - +  TypeSourceInfo *Sig = 0; +  QualType T = GetTypeForDeclarator(ParamInfo, CurScope, &Sig); +  CurBlock->TheDecl->setSignatureAsWritten(Sig); + +  QualType RetTy; +  if (const FunctionType *Fn = T->getAs<FunctionType>()) { +    RetTy = Fn->getResultType(); +    CurBlock->hasPrototype = isa<FunctionProtoType>(Fn); +    CurBlock->isVariadic = +      !isa<FunctionProtoType>(Fn) || cast<FunctionProtoType>(Fn)->isVariadic(); +  } else { +    RetTy = T;      CurBlock->hasPrototype = true;      CurBlock->isVariadic = false; -    // Check for a valid sentinel attribute on this block. -    if (CurBlock->TheDecl->getAttr<SentinelAttr>()) { -      Diag(ParamInfo.getAttributes()->getLoc(), -           diag::warn_attribute_sentinel_not_variadic) << 1; -      // FIXME: remove the attribute. -    } -    QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType(); - -    // Do not allow returning a objc interface by-value. -    if (RetTy->isObjCObjectType()) { -      Diag(ParamInfo.getSourceRange().getBegin(), -           diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; -      return; -    } +  } -    CurBlock->ReturnType = RetTy; +  CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); + +  // Don't allow returning an array by value. +  if (RetTy->isArrayType()) { +    Diag(ParamInfo.getSourceRange().getBegin(), diag::err_block_returns_array);      return;    } -  // Analyze arguments to block. -  assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function && -         "Not a function declarator!"); -  DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun; +  // Don't allow returning a objc interface by value. +  if (RetTy->isObjCObjectType()) { +    Diag(ParamInfo.getSourceRange().getBegin(), +         diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; +    return; +  } -  CurBlock->hasPrototype = FTI.hasPrototype; -  CurBlock->isVariadic = true; +  // Context.DependentTy is used as a placeholder for a missing block +  // return type. +  if (RetTy != Context.DependentTy) +    CurBlock->ReturnType = RetTy; -  // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes -  // no arguments, not a function that takes a single void argument. -  if (FTI.hasPrototype && -      FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && -     (!FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType().getCVRQualifiers()&& -        FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType())) { -    // empty arg list, don't push any params. -    CurBlock->isVariadic = false; -  } else if (FTI.hasPrototype) { -    for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { -      ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>(); +  // Push block parameters from the declarator if we had them. +  if (isa<FunctionProtoType>(T)) { +    FunctionProtoTypeLoc TL = cast<FunctionProtoTypeLoc>(Sig->getTypeLoc()); +    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { +      ParmVarDecl *Param = TL.getArg(I);        if (Param->getIdentifier() == 0 &&            !Param->isImplicit() &&            !Param->isInvalidDecl() && @@ -7039,13 +7024,39 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {          Diag(Param->getLocation(), diag::err_parameter_name_omitted);        CurBlock->Params.push_back(Param);      } -    CurBlock->isVariadic = FTI.isVariadic; + +  // Fake up parameter variables if we have a typedef, like +  //   ^ fntype { ... } +  } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) { +    for (FunctionProtoType::arg_type_iterator +           I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) { +      ParmVarDecl *Param = +        BuildParmVarDeclForTypedef(CurBlock->TheDecl, +                                   ParamInfo.getSourceRange().getBegin(), +                                   *I); +      CurBlock->Params.push_back(Param); +    }    } -  CurBlock->TheDecl->setParams(CurBlock->Params.data(), -                               CurBlock->Params.size()); -  CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); + +  // Set the parmaeters on the block decl. +  if (!CurBlock->Params.empty()) +    CurBlock->TheDecl->setParams(CurBlock->Params.data(), +                                 CurBlock->Params.size()); + +  // Finally we can process decl attributes.    ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); +  if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { +    Diag(ParamInfo.getAttributes()->getLoc(), +         diag::warn_attribute_sentinel_not_variadic) << 1; +    // FIXME: remove the attribute. +  } + +  // Put the parameter variables in scope.  We can bail out immediately +  // if we don't have any. +  if (CurBlock->Params.empty()) +    return; +    bool ShouldCheckShadow =      Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored; @@ -7061,25 +7072,6 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {        PushOnScopeChains(*AI, CurBlock->TheScope);      }    } - -  // Check for a valid sentinel attribute on this block. -  if (!CurBlock->isVariadic && -      CurBlock->TheDecl->getAttr<SentinelAttr>()) { -    Diag(ParamInfo.getAttributes()->getLoc(), -         diag::warn_attribute_sentinel_not_variadic) << 1; -    // FIXME: remove the attribute. -  } - -  // Analyze the return type. -  QualType T = GetTypeForDeclarator(ParamInfo, CurScope); -  QualType RetTy = T->getAs<FunctionType>()->getResultType(); - -  // Do not allow returning a objc interface by-value. -  if (RetTy->isObjCObjectType()) { -    Diag(ParamInfo.getSourceRange().getBegin(), -         diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; -  } else if (!RetTy->isDependentType()) -    CurBlock->ReturnType = RetTy;  }  /// ActOnBlockError - If there is an error parsing a block, this callback | 

