From: Steve Naroff Date: Fri, 3 Oct 2008 15:04:50 +0000 (+0000) Subject: - Add a convenience constructor to Type. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83ba14e260193a67bba3772134d1d428a1b1c394;p=clang - Add a convenience constructor to Type. - Many rewriter modifications. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57003 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/RewriteBlocks.cpp b/Driver/RewriteBlocks.cpp index 103072cff6..ea03650b97 100644 --- a/Driver/RewriteBlocks.cpp +++ b/Driver/RewriteBlocks.cpp @@ -540,7 +540,7 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) { // Finish writing the constructor. // FIXME: handle NSConcreteGlobalBlock. Constructor += ", int flags=0) {\n"; - Constructor += " impl.isa = &_NSConcreteStackBlock;\n impl.Size = sizeof("; + Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof("; Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n"; // Initialize all "by copy" arguments. @@ -559,10 +559,16 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) { Constructor += Name + " = _"; Constructor += Name + ";\n"; } - Constructor += " "; - Constructor += "}\n"; - S += Constructor; + } else { + // Finish writing the constructor. + // FIXME: handle NSConcreteGlobalBlock. + Constructor += ", int flags=0) {\n"; + Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof("; + Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n"; } + Constructor += " "; + Constructor += "}\n"; + S += Constructor; S += "};\n"; return S; } @@ -654,6 +660,17 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { RewriteBlockPointerDecl(TD); return; } + if (RecordDecl *RD = dyn_cast(D)) { + if (RD->isDefinition()) { + for (RecordDecl::field_const_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) { + FieldDecl *FD = *i; + if (isBlockPointerType(FD->getType())) + RewriteBlockPointerDecl(FD); + } + } + return; + } } void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) { @@ -733,6 +750,9 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { } else if (BlockDeclRefExpr *CDRE = dyn_cast(Exp->getCallee())) { closureName = CDRE->getDecl()->getName(); CPT = CDRE->getType()->getAsBlockPointerType(); + } else if (MemberExpr *MExpr = dyn_cast(Exp->getCallee())) { + closureName = MExpr->getMemberDecl()->getName(); + CPT = MExpr->getType()->getAsBlockPointerType(); } else { assert(1 && "RewriteBlockClass: Bad type"); } @@ -755,12 +775,17 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { } BlockCall += "))"; // close the argument list and paren expression. - // Invoke the closure. - BlockCall += closureName; - BlockCall += "->Invoke)"; + // Invoke the closure. We need to cast it since the declaration type is + // bogus (it's a function pointer type) + BlockCall += "((struct __block_impl *)"; + std::string closureExprBufStr; + llvm::raw_string_ostream closureExprBuf(closureExprBufStr); + Exp->getCallee()->printPretty(closureExprBuf); + BlockCall += closureExprBuf.str(); + BlockCall += ")->FuncPtr)"; // Add the arguments. - BlockCall += "("; + BlockCall += "((struct __block_impl *)"; BlockCall += closureName; for (CallExpr::arg_iterator I = Exp->arg_begin(), E = Exp->arg_end(); I != E; ++I) { @@ -903,6 +928,8 @@ void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) { DeclT = VD->getType(); else if (TypedefDecl *TDD = dyn_cast(ND)) DeclT = TDD->getUnderlyingType(); + else if (FieldDecl *FD = dyn_cast(ND)) + DeclT = FD->getType(); else assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled"); @@ -965,16 +992,22 @@ void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp) { } std::string BlockNumber = utostr(Blocks.size()-1); - std::string Tag = "struct __" + FuncName + "_block_impl_" + BlockNumber; + std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; + std::string FunkTypeStr; + + // Get a pointer to the function type so we can cast appropriately. + Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr); + // Rewrite the closure block with a compound literal. The first cast is // to prevent warnings from the C compiler. - std::string Init = "(struct __block_impl *)&(" + Tag + "){{0,"; + std::string Init = "(" + FunkTypeStr; + + Init += ")&" + Tag; - // Initialize the Flags, Size, and Invoke fields. - Init += (haveByRefDecls ? "HAS_BYREF," : "0,"); - Init += "sizeof(" + Tag + ")," + Func + "}"; + // Initialize the block function. + Init += "((void*)" + Func; // Add initializers for any closure decl refs. if (BlockDeclRefs.size()) { @@ -997,7 +1030,7 @@ void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp) { Init += (*I)->getName(); } } - Init += "}"; + Init += ")"; BlockDeclRefs.clear(); BlockByRefDecls.clear(); BlockByCopyDecls.clear(); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 598f4a3081..81417f0da6 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -92,6 +92,13 @@ public: ThePtr |= Quals; } + QualType(const Type *Ptr, unsigned Quals) { + assert((Quals & ~CVRFlags) == 0 && "Invalid type qualifiers!"); + ThePtr = reinterpret_cast(Ptr); + assert((ThePtr & CVRFlags) == 0 && "Type pointer not 8-byte aligned?"); + ThePtr |= Quals; + } + static QualType getFromOpaquePtr(void *Ptr) { QualType T; T.ThePtr = reinterpret_cast(Ptr);