Simplify: don't loop over everything to find the WrapperFD but use the one stored in the transaction.

git-svn-id: http://root.cern.ch/svn/root/trunk@47163 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
Axel Naumann 2012-11-11 12:47:05 +00:00
parent 1a9a90a836
commit 8416a9183c
4 changed files with 135 additions and 157 deletions

View File

@ -32,105 +32,93 @@ namespace cling {
if (!getTransaction()->getCompilationOpts().DeclarationExtraction)
return;
for (Transaction::const_iterator I = getTransaction()->decls_begin(),
E = getTransaction()->decls_end(); I != E; ++I)
for (DeclGroupRef::const_iterator J = (*I).begin(),
JE = (*I).end(); J != JE; ++J)
if(!ExtractDecl(*J))
setTransaction(0); // On error set to NULL.
if(!ExtractDecl(getTransaction()->getWrapperFD()))
setTransaction(0); // On error set to NULL.
}
bool DeclExtractor::ExtractDecl(Decl* D) {
FunctionDecl* FD = dyn_cast<FunctionDecl>(D);
bool DeclExtractor::ExtractDecl(FunctionDecl* FD) {
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;
if (FD) {
if (!utils::Analyze::IsWrapper(FD))
return true;
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;
}
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 (DeclStmt::decl_iterator J = DS->decl_begin();
J != DS->decl_end(); ++J) {
NamedDecl* ND = dyn_cast<NamedDecl>(*J);
if (ND) {
DeclContext* OldDC = ND->getDeclContext();
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);
}
// force recalc of the linkage (to external)
ND->ClearLinkageCache();
TouchedDecls.push_back(ND);
// 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);
}
// 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),
}
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);
// 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);
}
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]));
}
// 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;
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;
}
///\brief Checks for clashing names when trying to extract a declaration.

View File

@ -39,10 +39,10 @@ namespace cling {
///\brief Tries to extract the declaration on the global scope (translation
/// unit scope).
///
///\param D[in] - The declaration to be extracted.
///\param D[in] - The function declaration to extract from.
///\returns true on success.
///
bool ExtractDecl(clang::Decl* D);
bool ExtractDecl(clang::FunctionDecl* FD);
///\brief Checks for clashing names when trying to extract a declaration.
///

View File

@ -46,80 +46,70 @@ namespace cling {
== CompilationOptions::VPDisabled)
return;
for (Transaction::const_iterator I = getTransaction()->decls_begin(),
E = getTransaction()->decls_end(); I != E; ++I)
if(!tryAttachVP(*I))
return setTransaction(0); // On error set to NULL.
if (!tryAttachVP(getTransaction()->getWrapperFD()))
return setTransaction(0); // On error set to NULL.
}
bool ValuePrinterSynthesizer::tryAttachVP(DeclGroupRef DGR) {
for (DeclGroupRef::iterator I = DGR.begin(), E = DGR.end(); I != E; ++I)
if (FunctionDecl* FD = dyn_cast<FunctionDecl>(*I)) {
if (!utils::Analyze::IsWrapper(FD))
continue;
const CompilationOptions& CO(getTransaction()->getCompilationOpts());
if (CO.ValuePrinting == CompilationOptions::VPDisabled)
return true; // Nothing to do.
bool ValuePrinterSynthesizer::tryAttachVP(FunctionDecl* FD) {
// We have to be able to mark the expression for printout. There are
// three scenarios:
// 0: Expression printing disabled - don't do anything just exit.
// 1: Expression printing enabled - print no matter what.
// 2: Expression printing auto - analyze - rely on the omitted ';' to
// not produce the suppress marker.
int indexOfLastExpr = -1;
Expr* To = utils::Analyze::GetOrCreateLastExpr(FD, &indexOfLastExpr,
/*omitDS*/false,
m_Sema);
if (To) {
// Update the CompoundStmt body, avoiding alloc/dealloc of all the el.
CompoundStmt* CS = cast<CompoundStmt>(FD->getBody());
assert(CS && "Missing body?");
// We have to be able to mark the expression for printout. There are
// three scenarios:
// 0: Expression printing disabled - don't do anything just exit.
// 1: Expression printing enabled - print no matter what.
// 2: Expression printing auto - analyze - rely on the omitted ';' to
// not produce the suppress marker.
int indexOfLastExpr = -1;
Expr* To = utils::Analyze::GetOrCreateLastExpr(FD, &indexOfLastExpr,
/*omitDS*/false,
m_Sema);
if (To) {
// Update the CompoundStmt body, avoiding alloc/dealloc of all the el.
CompoundStmt* CS = cast<CompoundStmt>(FD->getBody());
assert(CS && "Missing body?");
switch (CO.ValuePrinting) {
case CompilationOptions::VPDisabled:
assert("Don't wait that long. Exit early!");
break;
case CompilationOptions::VPEnabled:
break;
case CompilationOptions::VPAuto:
if ((int)CS->size() > indexOfLastExpr+1
&& (*(CS->body_begin() + indexOfLastExpr + 1))
&& isa<NullStmt>(*(CS->body_begin() + indexOfLastExpr + 1)))
return true; // If next is NullStmt disable VP is disabled - exit.
break;
}
// We can't PushDeclContext, because we don't have scope.
Sema::ContextRAII pushedDC(*m_Sema, FD);
if (To) {
// Strip the parenthesis if any
if (ParenExpr* PE = dyn_cast<ParenExpr>(To))
To = PE->getSubExpr();
Expr* Result = 0;
if (m_Sema->getLangOpts().CPlusPlus)
Result = SynthesizeCppVP(To);
else
Result = SynthesizeVP(To);
if (Result)
*(CS->body_begin()+indexOfLastExpr) = Result;
}
// Clear the artificial NullStmt-s
if (!ClearNullStmts(CS)) {
// FIXME: Why it is here? Shouldn't it be in DeclExtractor?
// if no body remove the wrapper
DeclContext* DC = FD->getDeclContext();
Scope* S = m_Sema->getScopeForContext(DC);
if (S)
S->RemoveDecl(FD);
DC->removeDecl(FD);
}
}
const CompilationOptions& CO(getTransaction()->getCompilationOpts());
switch (CO.ValuePrinting) {
case CompilationOptions::VPDisabled:
assert("Don't wait that long. Exit early!");
break;
case CompilationOptions::VPEnabled:
break;
case CompilationOptions::VPAuto:
if ((int)CS->size() > indexOfLastExpr+1
&& (*(CS->body_begin() + indexOfLastExpr + 1))
&& isa<NullStmt>(*(CS->body_begin() + indexOfLastExpr + 1)))
return true; // If next is NullStmt disable VP is disabled - exit.
break;
}
// We can't PushDeclContext, because we don't have scope.
Sema::ContextRAII pushedDC(*m_Sema, FD);
if (To) {
// Strip the parenthesis if any
if (ParenExpr* PE = dyn_cast<ParenExpr>(To))
To = PE->getSubExpr();
Expr* Result = 0;
if (m_Sema->getLangOpts().CPlusPlus)
Result = SynthesizeCppVP(To);
else
Result = SynthesizeVP(To);
if (Result)
*(CS->body_begin()+indexOfLastExpr) = Result;
}
// Clear the artificial NullStmt-s
if (!ClearNullStmts(CS)) {
// FIXME: Why it is here? Shouldn't it be in DeclExtractor?
// if no body remove the wrapper
DeclContext* DC = FD->getDeclContext();
Scope* S = m_Sema->getScopeForContext(DC);
if (S)
S->RemoveDecl(FD);
DC->removeDecl(FD);
}
}
return true;
}

View File

@ -14,7 +14,7 @@
namespace clang {
class ASTContext;
class CompoundStmt;
class DeclGroupRef;
class FunctionDecl;
class Expr;
class Sema;
}
@ -52,13 +52,13 @@ public:
///\brief Tries to attach a value printing mechanism to the given decl group
/// ref.
///
///\param[in] DGR - A decl group ref the value printer is being attached to.
///\param[in] FD - wrapper function that the value printer will attached to.
///
///\returns true if the attachment was considered as success. I.e. even if
/// even if the value printer wasn't attached because of the compilation
/// options disallowint it - it will return still true. Returns false on
/// critical error.
bool tryAttachVP(clang::DeclGroupRef DGR);
bool tryAttachVP(clang::FunctionDecl* FD);
clang::Expr* SynthesizeCppVP(clang::Expr* E);
clang::Expr* SynthesizeVP(clang::Expr* E);
unsigned ClearNullStmts(clang::CompoundStmt* CS);