Ejemplo n.º 1
0
void QStringAllocations::VisitFromLatin1OrUtf8(Stmt *stmt)
{
    CallExpr *callExpr = dyn_cast<CallExpr>(stmt);
    if (!callExpr)
        return;

    FunctionDecl *functionDecl = callExpr->getDirectCallee();
    if (!StringUtils::functionIsOneOf(functionDecl, {"fromLatin1", "fromUtf8"}))
        return;

    CXXMethodDecl *methodDecl = dyn_cast<CXXMethodDecl>(functionDecl);
    if (!StringUtils::isOfClass(methodDecl, "QString"))
        return;

    if (!Utils::callHasDefaultArguments(callExpr) || !hasCharPtrArgument(functionDecl, 2)) // QString::fromLatin1("foo", 1) is ok
        return;

    if (!containsStringLiteralNoCallExpr(callExpr))
        return;

    if (!isOptionSet("no-msvc-compat")) {
        StringLiteral *lt = stringLiteralForCall(callExpr);
        if (lt && lt->getNumConcatenated() > 1) {
            return; // Nothing to do here, MSVC doesn't like it
        }
    }

    vector<ConditionalOperator*> ternaries;
    HierarchyUtils::getChilds(callExpr, ternaries, 2);
    if (!ternaries.empty()) {
        auto ternary = ternaries[0];
        if (Utils::ternaryOperatorIsOfStringLiteral(ternary)) {
            emitWarning(stmt->getLocStart(), string("QString::fromLatin1() being passed a literal"));
        }

        return;
    }

    std::vector<FixItHint> fixits;

    if (isFixitEnabled(FromLatin1_FromUtf8Allocations)) {
        const FromFunction fromFunction = functionDecl->getNameAsString() == "fromLatin1" ? FromLatin1 : FromUtf8;
        fixits = fixItReplaceFromLatin1OrFromUtf8(callExpr, fromFunction);
    }

    if (functionDecl->getNameAsString() == "fromLatin1") {
        emitWarning(stmt->getLocStart(), string("QString::fromLatin1() being passed a literal"), fixits);
    } else {
        emitWarning(stmt->getLocStart(), string("QString::fromUtf8() being passed a literal"), fixits);
    }
}
Ejemplo n.º 2
0
void RuleOfTwoSoft::VisitStmt(Stmt *s)
{
    CXXOperatorCallExpr *op = dyn_cast<CXXOperatorCallExpr>(s);
    if (op) {
        FunctionDecl *func = op->getDirectCallee();
        if (func && func->getNameAsString() == "operator=") {
            CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(func);
            if (method && method->getParent()) {
                CXXRecordDecl *record = method->getParent();
                const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
                const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
                if (hasCopyCtor && !hasCopyAssignOp && !isBlacklisted(record)) {
                    string msg = "Using assign operator but class " + record->getQualifiedNameAsString() + " has copy-ctor but no assign operator";
                    emitWarning(s->getLocStart(), msg);
                }
            }
        }
    } else if (CXXConstructExpr *ctorExpr = dyn_cast<CXXConstructExpr>(s)) {
        CXXConstructorDecl *ctorDecl = ctorExpr->getConstructor();
        CXXRecordDecl *record = ctorDecl->getParent();
        if (ctorDecl->isCopyConstructor() && record) {
            const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
            const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
            if (!hasCopyCtor && hasCopyAssignOp && !isBlacklisted(record)) {
                string msg = "Using copy-ctor but class " + record->getQualifiedNameAsString() + " has a trivial copy-ctor but non trivial assign operator";
                emitWarning(s->getLocStart(), msg);
            }
        }
    }
}
Ejemplo n.º 3
0
void QGetEnv::VisitStmt(clang::Stmt *stmt)
{
    // Lets check only in function calls. Otherwise there are too many false positives, it's common
    // to implicit cast to bool when checking pointers for validity, like if (ptr)

    CXXMemberCallExpr *memberCall = dyn_cast<CXXMemberCallExpr>(stmt);
    if (!memberCall)
        return;

    CXXMethodDecl *method = memberCall->getMethodDecl();
    if (!method)
        return;

    CXXRecordDecl *record = method->getParent();
    if (!record || record->getNameAsString() != "QByteArray") {
        return;
    }

    std::vector<CallExpr *> calls = Utils::callListForChain(memberCall);
    if (calls.size() != 2)
        return;

    CallExpr *qgetEnvCall = calls.back();

    FunctionDecl *func = qgetEnvCall->getDirectCallee();

    if (!func || func->getNameAsString() != "qgetenv")
        return;

    string methodname = method->getNameAsString();
    string errorMsg;
    std::string replacement;
    if (methodname == "isEmpty") {
        errorMsg = "qgetenv().isEmpty() allocates.";
        replacement = "qEnvironmentVariableIsEmpty";
    } else if (methodname == "isNull") {
        errorMsg = "qgetenv().isNull() allocates.";
        replacement = "qEnvironmentVariableIsSet";
    } else if (methodname == "toInt") {
        errorMsg = "qgetenv().toInt() is slow.";
        replacement = "qEnvironmentVariableIntValue";
    }

    if (!errorMsg.empty()) {
        std::vector<FixItHint> fixits;
        if (isFixitEnabled(FixitAll)) {
            const bool success = FixItUtils::transformTwoCallsIntoOne(m_ci, qgetEnvCall, memberCall, replacement, fixits);
            if (!success) {
                queueManualFixitWarning(memberCall->getLocStart(), FixitAll);
            }
        }

        errorMsg += " Use " + replacement + "() instead";
        emitWarning(memberCall->getLocStart(), errorMsg.c_str(), fixits);
    }
}
Ejemplo n.º 4
0
void FunctionArgsByRef::VisitDecl(Decl *decl)
{
    FunctionDecl *functionDecl = dyn_cast<FunctionDecl>(decl);
    if (functionDecl == nullptr || !functionDecl->hasBody() || shouldIgnoreFunction(functionDecl->getNameAsString())
            || !functionDecl->isThisDeclarationADefinition()) return;

    Stmt *body = functionDecl->getBody();

    for (auto it = functionDecl->param_begin(), end = functionDecl->param_end(); it != end; ++it) {
        const ParmVarDecl *param = *it;
        QualType paramQt = param->getType();
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (paramType == nullptr || paramType->isDependentType())
            continue;

        const int size_of_T = m_ci.getASTContext().getTypeSize(paramQt) / 8;
        const bool isSmall = size_of_T <= 16; // TODO: What about arm ?
        CXXRecordDecl *recordDecl = paramType->getAsCXXRecordDecl();
        const bool isUserNonTrivial = recordDecl && (recordDecl->hasUserDeclaredCopyConstructor() || recordDecl->hasUserDeclaredDestructor());
        const bool isReference = paramType->isLValueReferenceType();
        const bool isConst = paramQt.isConstQualified();
        if (recordDecl && shouldIgnoreClass(recordDecl->getQualifiedNameAsString()))
            continue;

        std::string error;
        if (isConst && !isReference) {
            if (!isSmall) {
                error += warningMsgForSmallType(size_of_T, paramQt.getAsString());
            } else if (isUserNonTrivial) {
                error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString();
            }
        } else if (isConst && isReference && !isUserNonTrivial && isSmall) {
            //error += "Don't use by-ref on small trivial type";
        } else if (!isConst && !isReference && (!isSmall || isUserNonTrivial)) {
            if (Utils::containsNonConstMemberCall(body, param) || Utils::containsCallByRef(body, param))
                continue;
            if (!isSmall) {
                error += warningMsgForSmallType(size_of_T, paramQt.getAsString());
            } else if (isUserNonTrivial) {
                error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString();
            }
        }

        if (!error.empty()) {
            emitWarning(param->getLocStart(), error.c_str());
        }
    }
}
  void NullDerefProtectionTransformer::Transform() {
    using namespace clang;
    FunctionDecl* FD = getTransaction()->getWrapperFD();
    if (!FD)
      return;

    // Copied from Interpreter.cpp;
    if (!m_MangleCtx)
      m_MangleCtx.reset(FD->getASTContext().createMangleContext());

    std::string mangledName;
    if (m_MangleCtx->shouldMangleDeclName(FD)) {
      llvm::raw_string_ostream RawStr(mangledName);
      switch(FD->getKind()) {
      case Decl::CXXConstructor:
        //Ctor_Complete,          // Complete object ctor
        //Ctor_Base,              // Base object ctor
        //Ctor_CompleteAllocating // Complete object allocating ctor (unused)
        m_MangleCtx->mangleCXXCtor(cast<CXXConstructorDecl>(FD), 
                                   Ctor_Complete, RawStr);
        break;

      case Decl::CXXDestructor:
        //Dtor_Deleting, // Deleting dtor
        //Dtor_Complete, // Complete object dtor
        //Dtor_Base      // Base object dtor
        m_MangleCtx->mangleCXXDtor(cast<CXXDestructorDecl>(FD),
                                   Dtor_Deleting, RawStr);
        break;

      default :
        m_MangleCtx->mangleName(FD, RawStr);
        break;
      }
      RawStr.flush();
    } else {
      mangledName = FD->getNameAsString();
    }
    
    // Find the function in the module.
    llvm::Function* F = getTransaction()->getModule()->getFunction(mangledName);
    if (F)
      runOnFunction(*F);
  }
Ejemplo n.º 6
0
Archivo: Utils.cpp Proyecto: KDE/clazy
bool Utils::isAssignOperator(CXXOperatorCallExpr *op, const std::string &className,
                             const std::string &argumentType, const clang::LangOptions &lo)
{
    if (!op)
        return false;

    FunctionDecl *functionDecl = op->getDirectCallee();
    if (!functionDecl)
        return false;

    CXXMethodDecl *methodDecl = dyn_cast<clang::CXXMethodDecl>(functionDecl);
    if (!className.empty() && !StringUtils::isOfClass(methodDecl, className))
        return false;

    if (functionDecl->getNameAsString() != "operator=" || functionDecl->param_size() != 1)
        return false;

    if (!argumentType.empty() && !StringUtils::hasArgumentOfType(functionDecl, argumentType, lo)) {
        return false;
    }

    return true;
}
Ejemplo n.º 7
0
 /// Skip the 'skipMe' function.
 bool shouldSkipFunctionBody(Decl *D) override {
   FunctionDecl *F = dyn_cast<FunctionDecl>(D);
   return F && F->getNameAsString() == "skipMe";
 }
Ejemplo n.º 8
0
/* Does the given statement look like:
 *  • g_return_if_fail(…)
 *  • g_return_val_if_fail(…)
 *  • g_assert(…)
 *  • g_assert_*(…)
 *  • assert(…)
 * This is complicated by the fact that if the gmessages.h header isn’t
 * available, they’ll present as CallExpr function calls with those names; if it
 * is available, they’ll be expanded as macros and turn into DoStmts with misc.
 * rubbish beneath.
 *
 * If the statement changes program state at all, return NULL. Otherwise, return
 * the condition which holds for the assertion to be bypassed (i.e. for the
 * assertion to succeed). This function is built recursively, building a boolean
 * expression for the condition based on avoiding branches which call
 * abort()-like functions.
 *
 * This function is based on a transformation of the AST to an augmented boolean
 * expression, using rules documented in each switch case. In this
 * documentation, calc(S) refers to the transformation function. The augmented
 * boolean expressions can be either NULL, or a normal boolean expression
 * (TRUE, FALSE, ∧, ∨, ¬). NULL is used iff the statement potentially changes
 * program state, and poisons any boolean expression:
 *     B ∧ NULL ≡ NULL
 *     B ∨ NULL ≡ NULL
 *     ¬NULL ≡ NULL
 */
Expr*
AssertionExtracter::is_assertion_stmt (Stmt& stmt, const ASTContext& context)
{
	DEBUG ("Checking " << stmt.getStmtClassName () << " for assertions.");

	/* Slow path: walk through the AST, aborting on statements which
	 * potentially mutate program state, and otherwise trying to find a base
	 * function call such as:
	 *  • g_return_if_fail_warning()
	 *  • g_assertion_message()
	 *  • g_assertion_message_*()
	 */
	switch ((int) stmt.getStmtClass ()) {
	case Stmt::StmtClass::CallExprClass: {
		/* Handle a direct function call.
		 * Transformations:
		 *     [g_return_if_fail|assert|…](C) ↦ C
		 *     [g_return_if_fail_warning|__assert_fail|…](C) ↦ FALSE
		 *     other_funcs(…) ↦ NULL */
		CallExpr& call_expr = cast<CallExpr> (stmt);
		FunctionDecl* func = call_expr.getDirectCallee ();
		if (func == NULL)
			return NULL;

		std::string func_name = func->getNameAsString ();
		DEBUG ("CallExpr to function " << func_name);

		if (_is_assertion_name (func_name)) {
			/* Assertion path where the compiler hasn't seen the
			 * definition of the assertion macro, so still thinks
			 * it's a function.
			 *
			 * Extract the assertion condition as the first function
			 * parameter.
			 *
			 * TODO: May need to fix up the condition for macros
			 * like g_assert_null(). */
			return call_expr.getArg (0);
		} else if (_is_assertion_fail_func_name (func_name)) {
			/* Assertion path where the assertion macro has been
			 * expanded and we're on the assertion failure branch.
			 *
			 * In this case, the assertion condition has been
			 * grabbed from an if statement already, so negate it
			 * (to avoid the failure condition) and return. */
			return new (context)
				IntegerLiteral (context, context.MakeIntValue (0, context.getLogicalOperationType ()),
				                context.getLogicalOperationType (),
				                SourceLocation ());
		}

		/* Not an assertion path. */
		return NULL;
	}
	case Stmt::StmtClass::DoStmtClass: {
		/* Handle a do { … } while (0) block (commonly used to allow
		 * macros to optionally be suffixed by a semicolon).
		 * Transformations:
		 *     do { S } while (0) ↦ calc(S)
		 *     do { S } while (C) ↦ NULL
		 * Note the second condition is overly-conservative. No
		 * solutions for the halting problem here. */
		DoStmt& do_stmt = cast<DoStmt> (stmt);
		Stmt* body = do_stmt.getBody ();
		Stmt* cond = do_stmt.getCond ();
		Expr* expr = dyn_cast<Expr> (cond);
		llvm::APSInt bool_expr;

		if (body != NULL &&
		    expr != NULL &&
		    expr->isIntegerConstantExpr (bool_expr, context) &&
		    !bool_expr.getBoolValue ()) {
			return is_assertion_stmt (*body, context);
		}

		return NULL;
	}
	case Stmt::StmtClass::IfStmtClass: {
		/* Handle an if(…) { … } else { … } block.
		 * Transformations:
		 *     if (C) { S1 } else { S2 } ↦
		 *       (C ∧ calc(S1)) ∨ (¬C ∧ calc(S2))
		 *     if (C) { S } ↦ (C ∧ calc(S)) ∨ ¬C
		 * i.e.
		 *     if (C) { S } ≡ if (C) { S } else {}
		 * where {} is an empty compound statement, below. */
		IfStmt& if_stmt = cast<IfStmt> (stmt);
		assert (if_stmt.getThen () != NULL);

		Expr* neg_cond = _negation_expr (if_stmt.getCond (), context);

		Expr* then_assertion =
			is_assertion_stmt (*(if_stmt.getThen ()), context);
		if (then_assertion == NULL)
			return NULL;

		then_assertion =
			_conjunction_expr (if_stmt.getCond (), then_assertion,
			                   context);

		if (if_stmt.getElse () == NULL)
			return _disjunction_expr (then_assertion, neg_cond,
			                          context);

		Expr* else_assertion =
			is_assertion_stmt (*(if_stmt.getElse ()), context);
		if (else_assertion == NULL)
			return NULL;

		else_assertion =
			_conjunction_expr (neg_cond, else_assertion, context);

		return _disjunction_expr (then_assertion, else_assertion,
		                          context);
	}
	case Stmt::StmtClass::ConditionalOperatorClass: {
		/* Handle a ternary operator.
		 * Transformations:
		 *     C ? S1 : S2 ↦
		 *       (C ∧ calc(S1)) ∨ (¬C ∧ calc(S2)) */
		ConditionalOperator& op_expr = cast<ConditionalOperator> (stmt);
		assert (op_expr.getTrueExpr () != NULL);
		assert (op_expr.getFalseExpr () != NULL);

		Expr* neg_cond = _negation_expr (op_expr.getCond (), context);

		Expr* then_assertion =
			is_assertion_stmt (*(op_expr.getTrueExpr ()), context);
		if (then_assertion == NULL)
			return NULL;

		then_assertion =
			_conjunction_expr (op_expr.getCond (), then_assertion,
			                   context);

		Expr* else_assertion =
			is_assertion_stmt (*(op_expr.getFalseExpr ()),
			                   context);
		if (else_assertion == NULL)
			return NULL;

		else_assertion =
			_conjunction_expr (neg_cond, else_assertion, context);

		return _disjunction_expr (then_assertion, else_assertion,
		                          context);
	}
	case Stmt::StmtClass::SwitchStmtClass: {
		/* Handle a switch statement.
		 * Transformations:
		 *     switch (C) { L1: S1; L2: S2; …; Lz: Sz } ↦ NULL
		 * FIXME: This should get a proper transformation sometime. */
		return NULL;
	}
	case Stmt::StmtClass::AttributedStmtClass: {
		/* Handle an attributed statement, e.g. G_LIKELY(…).
		 * Transformations:
		 *     att S ↦ calc(S) */
		AttributedStmt& attr_stmt = cast<AttributedStmt> (stmt);

		Stmt* sub_stmt = attr_stmt.getSubStmt ();
		if (sub_stmt == NULL)
			return NULL;

		return is_assertion_stmt (*sub_stmt, context);
	}
	case Stmt::StmtClass::CompoundStmtClass: {
		/* Handle a compound statement, e.g. { stmt1; stmt2; }.
		 * Transformations:
		 *     S1; S2; …; Sz ↦ calc(S1) ∧ calc(S2) ∧ … ∧ calc(Sz)
		 *     {} ↦ TRUE
		 *
		 * This is implemented by starting with a base TRUE case in the
		 * compound_condition, then taking the conjunction with the next
		 * statement’s assertion condition for each statement in the
		 * compound.
		 *
		 * If the compound is empty, the compound_condition will be
		 * TRUE. Otherwise, it will be (TRUE ∧ …), which will be
		 * simplified later. */
		CompoundStmt& compound_stmt = cast<CompoundStmt> (stmt);
		Expr* compound_condition =
			new (context)
				IntegerLiteral (context,
				                context.MakeIntValue (1, context.getLogicalOperationType ()),
				                context.getLogicalOperationType (),
				                SourceLocation ());

		for (CompoundStmt::const_body_iterator it =
		     compound_stmt.body_begin (),
		     ie = compound_stmt.body_end (); it != ie; ++it) {
			Stmt* body_stmt = *it;
			Expr* body_assertion =
				is_assertion_stmt (*body_stmt, context);

			if (body_assertion == NULL) {
				/* Reached a program state mutation. */
				return NULL;
			}

			/* Update the compound condition. */
			compound_condition =
				_conjunction_expr (compound_condition,
				                   body_assertion, context);

			DEBUG_EXPR ("Compound condition: ", *compound_condition);
		}

		return compound_condition;
	}
	case Stmt::StmtClass::GotoStmtClass:
		/* Handle a goto statement.
		 * Transformations:
		 *     goto L ↦ FALSE */
	case Stmt::StmtClass::ReturnStmtClass: {
		/* Handle a return statement.
		 * Transformations:
		 *     return ↦ FALSE */
		return new (context)
			IntegerLiteral (context,
			                context.MakeIntValue (0, context.getLogicalOperationType ()),
			                context.getLogicalOperationType (),
			                SourceLocation ());
	}
	case Stmt::StmtClass::NullStmtClass:
		/* Handle a null statement.
		 * Transformations:
		 *     ; ↦ TRUE */
	case Stmt::StmtClass::DeclRefExprClass:
		/* Handle a variable reference expression. These don’t modify
		 * program state.
		 * Transformations:
		 *     E ↦ TRUE */
	case Stmt::StmtClass::DeclStmtClass: {
		/* Handle a variable declaration statement. These don’t modify
		 * program state; they only introduce new state, so can’t affect
		 * subsequent assertions. (FIXME: For the moment, we ignore the
		 * possibility of the rvalue modifying program state.)
		 * Transformations:
		 *     T S1 ↦ TRUE
		 *     T S1 = S2 ↦ TRUE */
		return new (context)
			IntegerLiteral (context,
			                context.MakeIntValue (1, context.getLogicalOperationType ()),
			                context.getLogicalOperationType (),
			                SourceLocation ());
	}
	case Stmt::StmtClass::IntegerLiteralClass: {
		/* Handle an integer literal. This doesn’t modify program state,
		 * and evaluates directly to a boolean.
		 * Transformations:
		 *     0 ↦ FALSE
		 *     I ↦ TRUE */
		return dyn_cast<Expr> (&stmt);
	}
	case Stmt::StmtClass::ParenExprClass: {
		/* Handle a parenthesised expression.
		 * Transformations:
		 *     ( S ) ↦ calc(S) */
		ParenExpr& paren_expr = cast<ParenExpr> (stmt);

		Stmt* sub_expr = paren_expr.getSubExpr ();
		if (sub_expr == NULL)
			return NULL;

		return is_assertion_stmt (*sub_expr, context);
	}
	case Stmt::StmtClass::LabelStmtClass: {
		/* Handle a label statement.
		 * Transformations:
		 *     label: S ↦ calc(S) */
		LabelStmt& label_stmt = cast<LabelStmt> (stmt);

		Stmt* sub_stmt = label_stmt.getSubStmt ();
		if (sub_stmt == NULL)
			return NULL;

		return is_assertion_stmt (*sub_stmt, context);
	}
	case Stmt::StmtClass::ImplicitCastExprClass:
	case Stmt::StmtClass::CStyleCastExprClass: {
		/* Handle an explicit or implicit cast.
		 * Transformations:
		 *     (T) S ↦ calc(S) */
		CastExpr& cast_expr = cast<CastExpr> (stmt);

		Stmt* sub_expr = cast_expr.getSubExpr ();
		if (sub_expr == NULL)
			return NULL;

		return is_assertion_stmt (*sub_expr, context);
	}
	case Stmt::StmtClass::GCCAsmStmtClass:
	case Stmt::StmtClass::MSAsmStmtClass:
		/* Inline assembly. There is no way we are parsing this, so
		 * conservatively assume it modifies program state.
		 * Transformations:
		 *     A ↦ NULL */
	case Stmt::StmtClass::BinaryOperatorClass:
		/* Handle a binary operator statement. Since this is being
		 * processed at the top level, it’s most likely an assignment,
		 * so conservatively assume it modifies program state.
		 * Transformations:
		 *     S1 op S2 ↦ NULL */
	case Stmt::StmtClass::UnaryOperatorClass:
		/* Handle a unary operator statement. Since this is being
		 * processed at the top level, it’s not very interesting re.
		 * assertions, even though it probably won’t modify program
		 * state (unless it’s a pre- or post-increment or -decrement
		 * operator). Be conservative and assume it does, though.
		 * Transformations:
		 *     op S ↦ NULL */
	case Stmt::StmtClass::CompoundAssignOperatorClass:
		/* Handle a compound assignment operator, e.g. x += 5. This
		 * definitely modifies program state, so ignore it.
		 * Transformations:
		 *     S1 op S2 ↦ NULL */
	case Stmt::StmtClass::ForStmtClass:
		/* Handle a for statement. We assume these *always* change
		 * program state.
		 * Transformations:
		 *     for (…) { … } ↦ NULL */
	case Stmt::StmtClass::WhileStmtClass: {
		/* Handle a while(…) { … } block. Because we don't want to solve
		 * the halting problem, just assume all while statements cannot
		 * be assertion statements.
		 * Transformations:
		 *     while (C) { S } ↦ NULL
		 */
		return NULL;
	}
	case Stmt::StmtClass::NoStmtClass:
	default:
		WARN_EXPR (__func__ << "() can’t handle statements of type " <<
		           stmt.getStmtClassName (), stmt);
		return NULL;
	}
}
Ejemplo n.º 9
0
  bool DeclExtractor::ExtractDecl(Decl* D) {
    FunctionDecl* FD = dyn_cast<FunctionDecl>(D);

    if (FD) {
      if (FD->getNameAsString().find("__cling_Un1Qu3"))
        return true;

      llvm::SmallVector<NamedDecl*, 4> TouchedDecls;
      CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody());
      assert(CS && "Function body not a CompoundStmt?");
      DeclContext* DC = FD->getTranslationUnitDecl();
      Scope* TUScope = m_Sema->TUScope;
      assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?");
      llvm::SmallVector<Stmt*, 4> Stmts;

      for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end();
           I != EI; ++I) {
        DeclStmt* DS = dyn_cast<DeclStmt>(*I);
        if (!DS) {
          Stmts.push_back(*I);
          continue;
        }

        for (DeclStmt::decl_iterator J = DS->decl_begin();
             J != DS->decl_end(); ++J) {
          NamedDecl* ND = dyn_cast<NamedDecl>(*J);
          if (ND) {
            DeclContext* OldDC = ND->getDeclContext();

            // Make sure the decl is not found at its old possition
            OldDC->removeDecl(ND);
            if (Scope* S = m_Sema->getScopeForContext(OldDC)) {
              S->RemoveDecl(ND);
              m_Sema->IdResolver.RemoveDecl(ND);
            }

            if (ND->getDeclContext() == ND->getLexicalDeclContext())
              ND->setLexicalDeclContext(DC);
            else 
              assert("Not implemented: Decl with different lexical context");
            ND->setDeclContext(DC);

            if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
              VD->setStorageClass(SC_None);
              VD->setStorageClassAsWritten(SC_None);

              // if we want to print the result of the initializer of int i = 5
              // or the default initializer int i
              if (I+1 == EI || !isa<NullStmt>(*(I+1))) {
                QualType VDTy = VD->getType().getNonReferenceType();
                Expr* DRE = m_Sema->BuildDeclRefExpr(VD, VDTy,VK_LValue,
                                                     SourceLocation()
                                                     ).take();
                Stmts.push_back(DRE);
              }
            }
            // force recalc of the linkage (to external)
            ND->ClearLinkageCache();

            TouchedDecls.push_back(ND);
          }
        }
      }
      bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope);
      if (hasNoErrors) {
        for (size_t i = 0; i < TouchedDecls.size(); ++i) {
          m_Sema->PushOnScopeChains(TouchedDecls[i],
                                    m_Sema->getScopeForContext(DC),
                    /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i]));

          // The transparent DeclContexts (eg. scopeless enum) doesn't have 
          // scopes. While extracting their contents we need to update the
          // lookup tables and telling them to pick up the new possitions
          //  in the AST.
          if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) {
            if (InnerDC->isTransparentContext()) {
              // We can't PushDeclContext, because we don't have scope.
              Sema::ContextRAII pushedDC(*m_Sema, InnerDC);

              for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), 
                    DE = InnerDC->decls_end(); DI != DE ; ++DI) {
                if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI))
                  InnerDC->makeDeclVisibleInContext(ND);
              }
            }
          }

          // Append the new top level decl to the current transaction.
          getTransaction()->appendUnique(DeclGroupRef(TouchedDecls[i]));
        }
      }

      CS->setStmts(*m_Context, Stmts.data(), Stmts.size());

      // Put the wrapper after its declarations. (Nice when AST dumping)
      DC->removeDecl(FD);
      DC->addDecl(FD);

      return hasNoErrors;
    }
    return true;
  }