diff options
-rw-r--r-- | include/clang/AST/Decl.h | 14 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 4 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 27 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 9 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Checker/AnalysisConsumer.cpp | 14 | ||||
-rw-r--r-- | lib/Checker/CallInliner.cpp | 2 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 2 | ||||
-rw-r--r-- | lib/Checker/LLVMConventionsChecker.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 |
18 files changed, 74 insertions, 36 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 940f1b9187..d5a7ec029d 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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 { diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index f4d76f5241..317db014a6 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -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; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 6b52a17a21..149938fc5c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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(); } diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 7a104f4d57..0821da3b87 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -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(); diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 19c3ac1011..dd0fe08979 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -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:: diff --git a/lib/Checker/AnalysisConsumer.cpp b/lib/Checker/AnalysisConsumer.cpp index 35f5eecb38..524f37e396 100644 --- a/lib/Checker/AnalysisConsumer.cpp +++ b/lib/Checker/AnalysisConsumer.cpp @@ -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) diff --git a/lib/Checker/CallInliner.cpp b/lib/Checker/CallInliner.cpp index 88e1a05d11..c47e06c78f 100644 --- a/lib/Checker/CallInliner.cpp +++ b/lib/Checker/CallInliner.cpp @@ -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. diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index e5c9bb9eb5..d4a410e440 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -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. diff --git a/lib/Checker/LLVMConventionsChecker.cpp b/lib/Checker/LLVMConventionsChecker.cpp index 310af8a28e..0576f08e4e 100644 --- a/lib/Checker/LLVMConventionsChecker.cpp +++ b/lib/Checker/LLVMConventionsChecker.cpp @@ -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)) diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4f3572e1cc..7b7be9a260 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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. diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h index 4c790f92ab..abcafd6c9c 100644 --- a/lib/CodeGen/CGVTables.h +++ b/lib/CodeGen/CGVTables.h @@ -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 diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 86aaf9925a..cb83ffde6f 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d090e322f1..73de52476f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index db128185f2..b7e275a9d4 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e99fed3a12..df1143c5c9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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; } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 342c522442..93cec73d03 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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())) { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 9e454bc0f2..897acf39ce 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 06f38e88d5..853f7c3094 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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. |