forked from OSchip/llvm-project
Introduce Decl::hasBody() and FunctionDecl::hasBody() and use them instead of getBody() when we are just checking the existence of a body, to avoid de-serialization of the body from PCH.
Makes de-serialization of the function body even more "lazier". llvm-svn: 107768
This commit is contained in:
parent
a22e8148d4
commit
36ea322579
|
@ -1227,11 +1227,25 @@ public:
|
|||
EndRangeLoc = E;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the function has a body (definition). The
|
||||
/// function body might be in any of the (re-)declarations of this
|
||||
/// function. The variant that accepts a FunctionDecl pointer will
|
||||
/// set that function declaration to the actual declaration
|
||||
/// containing the body (if there is one).
|
||||
bool hasBody(const FunctionDecl *&Definition) const;
|
||||
|
||||
virtual bool hasBody() const {
|
||||
const FunctionDecl* Definition;
|
||||
return hasBody(Definition);
|
||||
}
|
||||
|
||||
/// getBody - Retrieve the body (definition) of the function. The
|
||||
/// function body might be in any of the (re-)declarations of this
|
||||
/// function. The variant that accepts a FunctionDecl pointer will
|
||||
/// set that function declaration to the actual declaration
|
||||
/// containing the body (if there is one).
|
||||
/// NOTE: For checking if there is a body, use hasBody() instead, to avoid
|
||||
/// unnecessary PCH de-serialization of the body.
|
||||
Stmt *getBody(const FunctionDecl *&Definition) const;
|
||||
|
||||
virtual Stmt *getBody() const {
|
||||
|
|
|
@ -488,6 +488,10 @@ public:
|
|||
/// top-level Stmt* of that body. Otherwise this method returns null.
|
||||
virtual Stmt* getBody() const { return 0; }
|
||||
|
||||
/// \brief Returns true if this Decl represents a declaration for a body of
|
||||
/// code, such as a function or method definition.
|
||||
virtual bool hasBody() const { return getBody() != 0; }
|
||||
|
||||
/// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt.
|
||||
CompoundStmt* getCompoundBody() const;
|
||||
|
||||
|
|
|
@ -953,6 +953,17 @@ bool FunctionDecl::isVariadic() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
|
||||
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
|
||||
if (I->Body) {
|
||||
Definition = *I;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
||||
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
|
||||
if (I->Body) {
|
||||
|
@ -1153,11 +1164,11 @@ bool FunctionDecl::isInlined() const {
|
|||
}
|
||||
|
||||
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
|
||||
Stmt *Pattern = 0;
|
||||
bool HasPattern = false;
|
||||
if (PatternDecl)
|
||||
Pattern = PatternDecl->getBody(PatternDecl);
|
||||
HasPattern = PatternDecl->hasBody(PatternDecl);
|
||||
|
||||
if (Pattern && PatternDecl)
|
||||
if (HasPattern && PatternDecl)
|
||||
return PatternDecl->isInlined();
|
||||
|
||||
return false;
|
||||
|
@ -1302,15 +1313,15 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
|
|||
|
||||
// Find the actual template from which we will instantiate.
|
||||
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
|
||||
Stmt *Pattern = 0;
|
||||
bool HasPattern = false;
|
||||
if (PatternDecl)
|
||||
Pattern = PatternDecl->getBody(PatternDecl);
|
||||
HasPattern = PatternDecl->hasBody(PatternDecl);
|
||||
|
||||
// C++0x [temp.explicit]p9:
|
||||
// Except for inline functions, other explicit instantiation declarations
|
||||
// have the effect of suppressing the implicit instantiation of the entity
|
||||
// to which they refer.
|
||||
if (!Pattern || !PatternDecl)
|
||||
if (!HasPattern || !PatternDecl)
|
||||
return true;
|
||||
|
||||
return PatternDecl->isInlined();
|
||||
|
@ -1514,7 +1525,7 @@ bool FunctionDecl::isOutOfLine() const {
|
|||
// class template, check whether that member function was defined out-of-line.
|
||||
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
|
||||
const FunctionDecl *Definition;
|
||||
if (FD->getBody(Definition))
|
||||
if (FD->hasBody(Definition))
|
||||
return Definition->isOutOfLine();
|
||||
}
|
||||
|
||||
|
@ -1522,7 +1533,7 @@ bool FunctionDecl::isOutOfLine() const {
|
|||
// check whether that function template was defined out-of-line.
|
||||
if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
|
||||
const FunctionDecl *Definition;
|
||||
if (FunTmpl->getTemplatedDecl()->getBody(Definition))
|
||||
if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
|
||||
return Definition->isOutOfLine();
|
||||
}
|
||||
|
||||
|
|
|
@ -452,6 +452,15 @@ CompoundStmt* Decl::getCompoundBody() const {
|
|||
}
|
||||
|
||||
SourceLocation Decl::getBodyRBrace() const {
|
||||
// Special handling of FunctionDecl to avoid de-serializing the body from PCH.
|
||||
// FunctionDecl stores EndRangeLoc for this purpose.
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
|
||||
const FunctionDecl *Definition;
|
||||
if (FD->hasBody(Definition))
|
||||
return Definition->getSourceRange().getEnd();
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
Stmt *Body = getBody();
|
||||
if (!Body)
|
||||
return SourceLocation();
|
||||
|
|
|
@ -743,7 +743,7 @@ bool CXXMethodDecl::hasInlineBody() const {
|
|||
CheckFn = this;
|
||||
|
||||
const FunctionDecl *fn;
|
||||
return CheckFn->getBody(fn) && !fn->isOutOfLine();
|
||||
return CheckFn->hasBody(fn) && !fn->isOutOfLine();
|
||||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::
|
||||
|
|
|
@ -180,7 +180,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void HandleTranslationUnit(ASTContext &C);
|
||||
void HandleCode(Decl *D, Stmt* Body, Actions& actions);
|
||||
void HandleCode(Decl *D, Actions& actions);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -209,7 +209,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
|
|||
FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
|
||||
break;
|
||||
DisplayFunction(FD);
|
||||
HandleCode(FD, FD->getBody(), FunctionActions);
|
||||
HandleCode(FD, FunctionActions);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -222,14 +222,14 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
|
|||
Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
|
||||
break;
|
||||
DisplayFunction(MD);
|
||||
HandleCode(MD, MD->getBody(), ObjCMethodActions);
|
||||
HandleCode(MD, ObjCMethodActions);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Decl::ObjCImplementation: {
|
||||
ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I);
|
||||
HandleCode(ID, 0, ObjCImplementationActions);
|
||||
HandleCode(ID, ObjCImplementationActions);
|
||||
|
||||
for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(),
|
||||
ME = ID->meth_end(); MI != ME; ++MI) {
|
||||
|
@ -237,7 +237,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
|
|||
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
||||
Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString())
|
||||
break;
|
||||
HandleCode(*MI, (*MI)->getBody(), ObjCMethodActions);
|
||||
HandleCode(*MI, ObjCMethodActions);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -270,7 +270,7 @@ static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
|
|||
FindBlocks(DC, WL);
|
||||
}
|
||||
|
||||
void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
|
||||
void AnalysisConsumer::HandleCode(Decl *D, Actions& actions) {
|
||||
|
||||
// Don't run the actions if an error has occured with parsing the file.
|
||||
Diagnostic &Diags = PP.getDiagnostics();
|
||||
|
@ -291,7 +291,7 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
|
|||
llvm::SmallVector<Decl*, 10> WL;
|
||||
WL.push_back(D);
|
||||
|
||||
if (Body && Opts.AnalyzeNestedBlocks)
|
||||
if (D->hasBody() && Opts.AnalyzeNestedBlocks)
|
||||
FindBlocks(cast<DeclContext>(D), WL);
|
||||
|
||||
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
|
||||
|
|
|
@ -42,7 +42,7 @@ bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
|
|||
if (!FD)
|
||||
return false;
|
||||
|
||||
if (!FD->getBody(FD))
|
||||
if (!FD->hasBody(FD))
|
||||
return false;
|
||||
|
||||
// Now we have the definition of the callee, create a CallEnter node.
|
||||
|
|
|
@ -1885,7 +1885,7 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
|
|||
if (!FD)
|
||||
return false;
|
||||
|
||||
if (!FD->getBody(FD))
|
||||
if (!FD->hasBody(FD))
|
||||
return false;
|
||||
|
||||
// Now we have the definition of the callee, create a CallEnter node.
|
||||
|
|
|
@ -294,7 +294,7 @@ static void ScanCodeDecls(DeclContext *DC, BugReporter &BR) {
|
|||
|
||||
Decl *D = *I;
|
||||
|
||||
if (D->getBody())
|
||||
if (D->hasBody())
|
||||
CheckStringRefAssignedTemporary(D, BR);
|
||||
|
||||
if (CXXRecordDecl *R = dyn_cast<CXXRecordDecl>(D))
|
||||
|
|
|
@ -98,7 +98,7 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
|
|||
/// emit. We can't emit aliases to declarations; that's just not
|
||||
/// how aliases work.
|
||||
const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
|
||||
if (!BaseD->isImplicit() && !BaseD->getBody())
|
||||
if (!BaseD->isImplicit() && !BaseD->hasBody())
|
||||
return true;
|
||||
|
||||
// If the base is at a non-zero offset, give up.
|
||||
|
|
|
@ -301,7 +301,7 @@ public:
|
|||
const CXXRecordDecl *RD) {
|
||||
assert (RD->isDynamicClass() && "Non dynamic classes have no key.");
|
||||
const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
|
||||
return KeyFunction && !KeyFunction->getBody();
|
||||
return KeyFunction && !KeyFunction->hasBody();
|
||||
}
|
||||
|
||||
/// needsVTTParameter - Return whether the given global decl needs a VTT
|
||||
|
|
|
@ -1085,7 +1085,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
|
|||
// If this class has a key function, use that to determine the linkage of
|
||||
// the vtable.
|
||||
const FunctionDecl *Def = 0;
|
||||
if (KeyFunction->getBody(Def))
|
||||
if (KeyFunction->hasBody(Def))
|
||||
KeyFunction = cast<CXXMethodDecl>(Def);
|
||||
|
||||
switch (KeyFunction->getTemplateSpecializationKind()) {
|
||||
|
@ -1453,7 +1453,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
|
|||
if (D->hasAttr<DLLExportAttr>()) {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
// The dllexport attribute is ignored for undefined symbols.
|
||||
if (FD->getBody())
|
||||
if (FD->hasBody())
|
||||
GA->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
} else {
|
||||
GA->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
|
|
|
@ -3488,7 +3488,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
if (Redeclaration && Previous.isSingleResult()) {
|
||||
const FunctionDecl *Def;
|
||||
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
|
||||
if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) {
|
||||
if (PrevFD && PrevFD->hasBody(Def) && D.hasAttributes()) {
|
||||
Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
|
||||
Diag(Def->getLocation(), diag::note_previous_definition);
|
||||
}
|
||||
|
@ -4530,7 +4530,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
|
|||
// But don't complain if we're in GNU89 mode and the previous definition
|
||||
// was an extern inline function.
|
||||
const FunctionDecl *Definition;
|
||||
if (FD->getBody(Definition) &&
|
||||
if (FD->hasBody(Definition) &&
|
||||
!canRedefineFunction(Definition, getLangOptions())) {
|
||||
Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
|
||||
Diag(Definition->getLocation(), diag::note_previous_definition);
|
||||
|
@ -5917,7 +5917,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
|
|||
typedef CXXRecordDecl::ctor_iterator ctor_iter;
|
||||
for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
|
||||
const FunctionDecl *body = 0;
|
||||
ci->getBody(body);
|
||||
ci->hasBody(body);
|
||||
if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) {
|
||||
SourceLocation CtorLoc = ci->getLocation();
|
||||
Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
|
||||
|
|
|
@ -913,7 +913,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
isDef = (!VD->hasExternalStorage() || VD->getInit());
|
||||
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
isDef = FD->getBody();
|
||||
isDef = FD->hasBody();
|
||||
} else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
|
||||
// We ignore weak import on properties and methods
|
||||
return;
|
||||
|
|
|
@ -6652,7 +6652,7 @@ bool Sema::DefineUsedVTables() {
|
|||
if (const CXXMethodDecl *KeyFunction
|
||||
= Context.getKeyFunction(DynamicClasses[I])) {
|
||||
const FunctionDecl *Definition = 0;
|
||||
if (KeyFunction->getBody(Definition))
|
||||
if (KeyFunction->hasBody(Definition))
|
||||
MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true);
|
||||
}
|
||||
}
|
||||
|
@ -6675,7 +6675,7 @@ bool Sema::DefineUsedVTables() {
|
|||
// defined in another translation unit, we don't need to emit the
|
||||
// vtable even though we're using it.
|
||||
const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
|
||||
if (KeyFunction && !KeyFunction->getBody()) {
|
||||
if (KeyFunction && !KeyFunction->hasBody()) {
|
||||
switch (KeyFunction->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
|
@ -6723,7 +6723,7 @@ bool Sema::DefineUsedVTables() {
|
|||
// Optionally warn if we're emitting a weak vtable.
|
||||
if (Class->getLinkage() == ExternalLinkage &&
|
||||
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
|
||||
if (!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined()))
|
||||
if (!KeyFunction || (KeyFunction->hasBody() && KeyFunction->isInlined()))
|
||||
Diag(Class->getLocation(), diag::warn_weak_vtable) << Class;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3676,7 +3676,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
|
|||
// Check if we have too few/too many template arguments, based
|
||||
// on our knowledge of the function definition.
|
||||
const FunctionDecl *Def = 0;
|
||||
if (FDecl->getBody(Def) && NumArgs != Def->param_size()) {
|
||||
if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
|
||||
const FunctionProtoType *Proto =
|
||||
Def->getType()->getAs<FunctionProtoType>();
|
||||
if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) {
|
||||
|
|
|
@ -1442,7 +1442,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
|||
SuppressNew)
|
||||
continue;
|
||||
|
||||
if (Function->getBody())
|
||||
if (Function->hasBody())
|
||||
continue;
|
||||
|
||||
if (TSK == TSK_ExplicitInstantiationDefinition) {
|
||||
|
@ -1452,7 +1452,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
|||
// specialization and is only an explicit instantiation definition
|
||||
// of members whose definition is visible at the point of
|
||||
// instantiation.
|
||||
if (!Pattern->getBody())
|
||||
if (!Pattern->hasBody())
|
||||
continue;
|
||||
|
||||
Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
||||
|
|
|
@ -1181,7 +1181,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
D->isThisDeclarationADefinition()) {
|
||||
// Check for a function body.
|
||||
const FunctionDecl *Definition = 0;
|
||||
if (Function->getBody(Definition) &&
|
||||
if (Function->hasBody(Definition) &&
|
||||
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
|
||||
SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
|
||||
<< Function->getDeclName();
|
||||
|
@ -1197,7 +1197,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
((*R)->getFriendObjectKind() != Decl::FOK_None)) {
|
||||
if (const FunctionDecl *RPattern
|
||||
= (*R)->getTemplateInstantiationPattern())
|
||||
if (RPattern->getBody(RPattern)) {
|
||||
if (RPattern->hasBody(RPattern)) {
|
||||
SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
|
||||
<< Function->getDeclName();
|
||||
SemaRef.Diag((*R)->getLocation(), diag::note_previous_definition);
|
||||
|
@ -2040,7 +2040,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
FunctionDecl *Function,
|
||||
bool Recursive,
|
||||
bool DefinitionRequired) {
|
||||
if (Function->isInvalidDecl() || Function->getBody())
|
||||
if (Function->isInvalidDecl() || Function->hasBody())
|
||||
return;
|
||||
|
||||
// Never instantiate an explicit specialization.
|
||||
|
|
Loading…
Reference in New Issue