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 119b3c8..7ee7c7b 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -177,6 +177,7 @@
// 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 @@
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 @@
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 @@
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 97227ce..c1e6a8f 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -354,6 +354,8 @@
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 4a3c4d4..9cc2291 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -285,12 +285,12 @@
} 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 9af75ae..391937b 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -67,6 +67,7 @@
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
void VisitBlockDecl(BlockDecl *BD);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+ void VisitObjCMethodDecl(ObjCMethodDecl *D);
};
}
@@ -159,6 +160,30 @@
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<CompoundStmt>(Reader.GetStmt(Record[Idx++])));
+ MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
+ MD->setCmdDecl(cast<ImplicitParamDecl>(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<ParmVarDecl *, 16> Params;
+ Params.reserve(NumParams);
+ for (unsigned I = 0; I != NumParams; ++I)
+ Params.push_back(cast<ParmVarDecl>(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 @@
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 9f22f13..6aea7a5 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -270,6 +270,7 @@
void VisitBlockDecl(BlockDecl *D);
void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
uint64_t VisibleOffset);
+ void VisitObjCMethodDecl(ObjCMethodDecl *D);
};
}
@@ -359,6 +360,32 @@
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 db81cac..b813e08 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1226,7 +1226,7 @@
} 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 @@
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 @@
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 0000000..97617be
--- /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 0000000..49137ea
--- /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];
+}