From: Steve Naroff Date: Mon, 20 Apr 2009 15:06:07 +0000 (+0000) Subject: Add pch reader/writer support for ObjCMethodDecl. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=53c9d8a4b8f0a76cb9dd2fdd8c433ccf110f2eec;p=clang Add pch reader/writer support for ObjCMethodDecl. Test will be enabled with ObjCInterfaceDecl is added. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69594 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 119b3c890a..7ee7c7b91b 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -177,6 +177,7 @@ public: // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } SourceLocation getLocEnd() const { return EndLoc; } + void setEndLoc(SourceLocation Loc) { EndLoc = Loc; } SourceRange getSourceRange() const { return SourceRange(getLocation(), EndLoc); } @@ -189,6 +190,7 @@ public: Selector getSelector() const { return getDeclName().getObjCSelector(); } unsigned getSynthesizedMethodSize() const; QualType getResultType() const { return MethodDeclType; } + void setResultType(QualType T) { MethodDeclType = T; } // Iterator access to formal parameters. unsigned param_size() const { return ParamInfo.size(); } @@ -196,8 +198,7 @@ public: param_iterator param_begin() const { return ParamInfo.begin(); } param_iterator param_end() const { return ParamInfo.end(); } - void setMethodParams(ParmVarDecl *const *List, unsigned Num, - ASTContext &C) { + void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num) { ParamInfo.set(List, Num, C); } @@ -219,15 +220,19 @@ public: void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID); ImplicitParamDecl * getSelfDecl() const { return SelfDecl; } + void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; } ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } + void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } bool isInstanceMethod() const { return IsInstance; } + void setInstanceMethod(bool isInst) { IsInstance = isInst; } bool isVariadic() const { return IsVariadic; } + void setVariadic(bool isVar) { IsVariadic = isVar; } bool isClassMethod() const { return !IsInstance; } bool isSynthesized() const { return IsSynthesized; } - void setIsSynthesized() { IsSynthesized = true; } + void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } // Related to protocols declared in @protocol void setDeclImplementation(ImplementationControl ic) { diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 97227ceadb..c1e6a8f493 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -354,6 +354,8 @@ namespace clang { DECL_ENUM_CONSTANT, /// \brief A FunctionDecl record. DECL_FUNCTION, + /// \brief A ObjCMethodDecl record. + DECL_OBJC_METHOD, /// \brief A FieldDecl record. DECL_FIELD, /// \brief A VarDecl record. diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 4a3c4d4f30..9cc22912ca 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -285,12 +285,12 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, } else // we have a factory method. selfTy = Context.getObjCClassType(); - SelfDecl = ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("self"), selfTy); + setSelfDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), + &Context.Idents.get("self"), selfTy)); - CmdDecl = ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("_cmd"), - Context.getObjCSelType()); + setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), + &Context.Idents.get("_cmd"), + Context.getObjCSelType())); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 9af75aef2b..391937b923 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -67,6 +67,7 @@ namespace { void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); void VisitBlockDecl(BlockDecl *BD); std::pair VisitDeclContext(DeclContext *DC); + void VisitObjCMethodDecl(ObjCMethodDecl *D); }; } @@ -159,6 +160,30 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setParams(Reader.getContext(), &Params[0], NumParams); } +void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { + VisitNamedDecl(MD); + if (Record[Idx++]) { + // In practice, this won't be executed (since method definitions + // don't occur in header files). + MD->setBody(cast(Reader.GetStmt(Record[Idx++]))); + MD->setSelfDecl(cast(Reader.GetDecl(Record[Idx++]))); + MD->setCmdDecl(cast(Reader.GetDecl(Record[Idx++]))); + } + MD->setInstanceMethod(Record[Idx++]); + MD->setVariadic(Record[Idx++]); + MD->setSynthesized(Record[Idx++]); + MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); + MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); + MD->setResultType(Reader.GetType(Record[Idx++])); + MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + unsigned NumParams = Record[Idx++]; + llvm::SmallVector Params; + Params.reserve(NumParams); + for (unsigned I = 0; I != NumParams; ++I) + Params.push_back(cast(Reader.GetDecl(Record[Idx++]))); + MD->setMethodParams(Reader.getContext(), &Params[0], NumParams); +} + void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { VisitValueDecl(FD); FD->setMutable(Record[Idx++]); @@ -1770,6 +1795,12 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { break; } + case pch::DECL_OBJC_METHOD: { + D = ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(), + Selector(), QualType(), 0); + break; + } + case pch::DECL_FIELD: { D = FieldDecl::Create(Context, 0, SourceLocation(), 0, QualType(), 0, false); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 9f22f13134..6aea7a5372 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -270,6 +270,7 @@ namespace { void VisitBlockDecl(BlockDecl *D); void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, uint64_t VisibleOffset); + void VisitObjCMethodDecl(ObjCMethodDecl *D); }; } @@ -359,6 +360,32 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Code = pch::DECL_FUNCTION; } +void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { + VisitNamedDecl(D); + // FIXME: convert to LazyStmtPtr? + // Unlike C/C++, method bodies will never be in header files. + Record.push_back(D->getBody() != 0); + if (D->getBody() != 0) { + Writer.AddStmt(D->getBody(Context)); + Writer.AddDeclRef(D->getSelfDecl(), Record); + Writer.AddDeclRef(D->getCmdDecl(), Record); + } + Record.push_back(D->isInstanceMethod()); + Record.push_back(D->isVariadic()); + Record.push_back(D->isSynthesized()); + // FIXME: stable encoding for @required/@optional + Record.push_back(D->getImplementationControl()); + // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway + Record.push_back(D->getObjCDeclQualifier()); + Writer.AddTypeRef(D->getResultType(), Record); + Writer.AddSourceLocation(D->getLocEnd(), Record); + Record.push_back(D->param_size()); + for (ObjCMethodDecl::param_iterator P = D->param_begin(), + PEnd = D->param_end(); P != PEnd; ++P) + Writer.AddDeclRef(*P, Record); + Code = pch::DECL_OBJC_METHOD; +} + void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { VisitValueDecl(D); Record.push_back(D->isMutable()); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index db81cacc2b..b813e085ee 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1226,7 +1226,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, } else // A user declared getter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation - GetterMethod->setIsSynthesized(); + GetterMethod->setSynthesized(true); property->setGetterMethodDecl(GetterMethod); // Skip setter if property is read-only. @@ -1252,12 +1252,12 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, property->getType(), VarDecl::None, 0); - SetterMethod->setMethodParams(&Argument, 1, Context); + SetterMethod->setMethodParams(Context, &Argument, 1); CD->addDecl(Context, SetterMethod); } else // A user declared setter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation - SetterMethod->setIsSynthesized(); + SetterMethod->setSynthesized(true); property->setSetterMethodDecl(SetterMethod); } // Add any synthesized methods to the global pool. This allows us to @@ -1506,7 +1506,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( Params.push_back(Param); } - ObjCMethod->setMethodParams(&Params[0], Sel.getNumArgs(), Context); + ObjCMethod->setMethodParams(Context, &Params[0], Sel.getNumArgs()); ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); const ObjCMethodDecl *PrevMethod = 0; diff --git a/test/PCH/methods.h b/test/PCH/methods.h new file mode 100644 index 0000000000..97617be293 --- /dev/null +++ b/test/PCH/methods.h @@ -0,0 +1,6 @@ +/* For use with the methods.m test */ + +@interface TestPCH ++ alloc; +- (void)instMethod; +@end diff --git a/test/PCH/methods.m b/test/PCH/methods.m new file mode 100644 index 0000000000..49137ea671 --- /dev/null +++ b/test/PCH/methods.m @@ -0,0 +1,11 @@ +// Test this without pch. +// FIXME: clang-cc -include %S/methods.h -fsyntax-only -verify %s && + +// Test with pch. +// FIXME: clang-cc -x=objective-c -emit-pch -o %t %S/methods.h && +// FIXME: clang-cc -include-pch %t -fsyntax-only -verify %s + +void func() { + TestPCH *xx = [TestPCH alloc]; + [xx instMethod]; +}