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 {
/// 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;
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) {
}
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;
// 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();
// 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();
}
// 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();
}
}
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();
CheckFn = this;
const FunctionDecl *fn;
- return CheckFn->getBody(fn) && !fn->isOutOfLine();
+ return CheckFn->hasBody(fn) && !fn->isOutOfLine();
}
CXXBaseOrMemberInitializer::
}
virtual void HandleTranslationUnit(ASTContext &C);
- void HandleCode(Decl *D, Stmt* Body, Actions& actions);
+ void HandleCode(Decl *D, Actions& actions);
};
} // end anonymous namespace
FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
break;
DisplayFunction(FD);
- HandleCode(FD, FD->getBody(), FunctionActions);
+ HandleCode(FD, FunctionActions);
}
break;
}
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) {
if (!Opts.AnalyzeSpecificFunction.empty() &&
Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString())
break;
- HandleCode(*MI, (*MI)->getBody(), ObjCMethodActions);
+ HandleCode(*MI, ObjCMethodActions);
}
}
break;
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();
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)
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.
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.
Decl *D = *I;
- if (D->getBody())
+ if (D->hasBody())
CheckStringRefAssignedTemporary(D, BR);
if (CXXRecordDecl *R = dyn_cast<CXXRecordDecl>(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.
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
// 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()) {
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);
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);
}
// 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);
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;
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;
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);
}
}
// 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:
// 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;
}
}
// 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())) {
SuppressNew)
continue;
- if (Function->getBody())
+ if (Function->hasBody())
continue;
if (TSK == TSK_ExplicitInstantiationDefinition) {
// 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);
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();
((*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);
FunctionDecl *Function,
bool Recursive,
bool DefinitionRequired) {
- if (Function->isInvalidDecl() || Function->getBody())
+ if (Function->isInvalidDecl() || Function->hasBody())
return;
// Never instantiate an explicit specialization.