From a67033294a028a9a33530bb3454758ba33acd842 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 19 Feb 2009 22:01:56 +0000 Subject: [PATCH] Add enough checking to ensure that non-constant block literals don't appear to be constant. I'll probably redo this and throw it all away later once we have codegen for BlockDeclRefExprs. llvm-svn: 65070 --- clang/include/clang/AST/Expr.h | 10 ++++++++-- clang/lib/AST/ExprConstant.cpp | 6 +++++- clang/lib/AST/StmtSerialization.cpp | 5 ++++- clang/lib/CodeGen/CGExprConstant.cpp | 6 +++++- clang/lib/Sema/Sema.h | 3 ++- clang/lib/Sema/SemaExpr.cpp | 6 +++++- 6 files changed, 29 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index d75d3667d5a6..3745866f75c0 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2051,9 +2051,11 @@ public: class BlockExpr : public Expr { protected: BlockDecl *TheBlock; + bool HasBlockDeclRefExprs; public: - BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty), - TheBlock(BD) {} + BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs) + : Expr(BlockExprClass, ty), + TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {} const BlockDecl *getBlockDecl() const { return TheBlock; } BlockDecl *getBlockDecl() { return TheBlock; } @@ -2070,6 +2072,10 @@ public: /// getFunctionType - Return the underlying function type for this block. const FunctionType *getFunctionType() const; + /// hasBlockDeclRefExprs - Return true iff the block has BlockDeclRefExpr + /// contained inside. + bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; } + static bool classof(const Stmt *T) { return T->getStmtClass() == BlockExprClass; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 540a6377f262..51c581a70838 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -260,7 +260,11 @@ public: APValue VisitAddrLabelExpr(AddrLabelExpr *E) { return APValue(E, 0); } APValue VisitCallExpr(CallExpr *E); - APValue VisitBlockExpr(BlockExpr *E) { return APValue(E, 0); } + APValue VisitBlockExpr(BlockExpr *E) { + if (!E->hasBlockDeclRefExprs()) + return APValue(E, 0); + return APValue(); + } APValue VisitConditionalOperator(ConditionalOperator *E); }; } // end anonymous namespace diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp index a6cf01fe2bab..009a2dd17a8f 100644 --- a/clang/lib/AST/StmtSerialization.cpp +++ b/clang/lib/AST/StmtSerialization.cpp @@ -1290,11 +1290,14 @@ ExtVectorElementExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C) { void BlockExpr::EmitImpl(Serializer& S) const { S.Emit(getType()); S.EmitOwnedPtr(TheBlock); + S.EmitBool(HasBlockDeclRefExprs); } BlockExpr* BlockExpr::CreateImpl(Deserializer& D, ASTContext& C) { QualType T = QualType::ReadVal(D); - return new BlockExpr(cast(D.ReadOwnedPtr(C)),T); + BlockDecl *B = cast(D.ReadOwnedPtr(C)); + bool H = D.ReadBool(); + return new BlockExpr(B,T,H); } void BlockDeclRefExpr::EmitImpl(Serializer& S) const { diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 523014f1fb13..8cfd60ce5c54 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -382,6 +382,8 @@ public: } llvm::Constant *VisitBlockExpr(const BlockExpr *E) { + assert (!E->hasBlockDeclRefExprs() && "global block with BlockDeclRefs"); + const char *Name = ""; if (const NamedDecl *ND = dyn_cast(CGF->CurFuncDecl)) Name = ND->getNameAsString().c_str(); @@ -615,7 +617,9 @@ public: return CGM.GetAddrOfConstantCFString(S); } case Expr::BlockExprClass: { - return CGF->BuildBlockLiteralTmp(cast(E)); + BlockExpr *B = cast(E); + if (!B->hasBlockDeclRefExprs()) + return CGF->BuildBlockLiteralTmp(B); } } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3eb68b50590d..2a4b4657be6b 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2004,7 +2004,8 @@ struct BlockSemaInfo { llvm::SmallVector Params; bool hasPrototype; bool isVariadic; - + bool hasBlockDeclRefExprs; + BlockDecl *TheDecl; /// TheScope - This is the scope for the block itself, which contains diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5d1d9353868c..c95b5ee52d6e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -865,6 +865,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // as they do not get snapshotted. // if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) { + // Blocks that have these can't be constant. + CurBlock->hasBlockDeclRefExprs = true; + // The BlocksAttr indicates the variable is bound by-reference. if (VD->getAttr()) return Owned(new (Context) BlockDeclRefExpr(VD, @@ -4331,6 +4334,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { BSI->ReturnType = 0; BSI->TheScope = BlockScope; + BSI->hasBlockDeclRefExprs = false; BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc); PushDeclContext(BlockScope, BSI->TheDecl); @@ -4442,7 +4446,7 @@ Sema::ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *body, BlockTy = Context.getBlockPointerType(BlockTy); BSI->TheDecl->setBody(Body.take()); - return new (Context) BlockExpr(BSI->TheDecl, BlockTy); + return new (Context) BlockExpr(BSI->TheDecl, BlockTy, BSI->hasBlockDeclRefExprs); } Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,