Added new C++ AST Decl subclasses.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52155 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h
index 07e9232..96e887c 100644
--- a/include/clang/AST/AST.h
+++ b/include/clang/AST/AST.h
@@ -17,6 +17,7 @@
// This header exports all AST interfaces.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 1bfad2e..c404e4f 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the Decl interface and subclasses.
+// This file defines the Decl subclasses.
//
//===----------------------------------------------------------------------===//
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/DeclBase.h"
+#include "clang/Parse/AccessSpecifier.h"
namespace clang {
class Expr;
@@ -382,11 +383,6 @@
/// function.
ScopedDecl *DeclChain;
- // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
- unsigned SClass : 2;
- bool IsInline : 1;
- bool IsImplicit : 1;
-
/// PreviousDeclaration - A link to the previous declaration of this
/// same function, NULL if this is the first declaration. For
/// example, in the following code, the PreviousDeclaration can be
@@ -398,13 +394,19 @@
/// int f(int x, int y) { return x + y; }
FunctionDecl *PreviousDeclaration;
- FunctionDecl(DeclContext *DC, SourceLocation L,
+ // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
+ unsigned SClass : 2;
+ bool IsInline : 1;
+ bool IsImplicit : 1;
+
+protected:
+ FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
StorageClass S, bool isInline, ScopedDecl *PrevDecl)
- : ValueDecl(Function, DC, L, Id, T, PrevDecl),
- DeclContext(Function),
- ParamInfo(0), Body(0), DeclChain(0), SClass(S),
- IsInline(isInline), IsImplicit(0), PreviousDeclaration(0) {}
+ : ValueDecl(DK, DC, L, Id, T, PrevDecl),
+ DeclContext(DK),
+ ParamInfo(0), Body(0), DeclChain(0), PreviousDeclaration(0),
+ SClass(S), IsInline(isInline), IsImplicit(0) {}
virtual ~FunctionDecl();
virtual void Destroy(ASTContext& C);
@@ -498,7 +500,9 @@
bool isInline() const { return IsInline; }
// Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return D->getKind() == Function; }
+ static bool classof(const Decl *D) {
+ return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
+ }
static bool classof(const FunctionDecl *D) { return true; }
protected:
@@ -608,6 +612,9 @@
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: ScopedDecl(DK, DC, L, Id, PrevDecl), TypeForDecl(0) {}
public:
+ void setAccess(AccessSpecifier AS) { Access = AS; }
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TypeFirst && D->getKind() <= TypeLast;
@@ -759,7 +766,8 @@
/// Members/NumMembers - This is a new[]'d array of pointers to Decls.
FieldDecl **Members; // Null if not defined.
int NumMembers; // -1 if not defined.
-
+
+protected:
RecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl) : TagDecl(DK, DC, L, Id, PrevDecl) {
HasFlexibleArrayMember = false;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index b4f4c3b..4bc2cc9 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -21,9 +21,11 @@
namespace clang {
class TranslationUnitDecl;
class NamespaceDecl;
+class ScopedDecl;
class FunctionDecl;
-class ObjCMethodDecl;
+class CXXRecordDecl;
class EnumDecl;
+class ObjCMethodDecl;
class ObjCInterfaceDecl;
/// Decl - This represents one declaration (or definition), e.g. a variable,
@@ -35,11 +37,13 @@
// This lists the concrete classes of Decl in order of the inheritance
// hierarchy. This allows us to do efficient classof tests based on the
// enums below. The commented out names are abstract class names.
+ // [DeclContext] indicatea that the class also inherits from DeclContext.
// Decl
- TranslationUnit,
+ TranslationUnit, // [DeclContext]
// NamedDecl
Field,
+ CXXField,
ObjCIvar,
ObjCCategory,
ObjCCategoryImpl,
@@ -47,23 +51,29 @@
ObjCProtocol,
ObjCProperty,
// ScopedDecl
- Namespace,
+ Namespace, // [DeclContext]
// TypeDecl
Typedef,
// TagDecl
- Enum,
+ Enum, // [DeclContext]
// RecordDecl
Struct,
Union,
Class,
+ // CXXRecordDecl [DeclContext]
+ CXXStruct,
+ CXXUnion,
+ CXXClass,
// ValueDecl
EnumConstant,
- Function,
+ Function, // [DeclContext]
+ CXXMethod,
Var,
+ CXXClassVar,
ParmVar,
- ObjCInterface,
+ ObjCInterface, // [DeclContext]
ObjCCompatibleAlias,
- ObjCMethod,
+ ObjCMethod, // [DeclContext]
ObjCClass,
ObjCForwardProtocol,
ObjCPropertyImpl,
@@ -72,14 +82,16 @@
// For each non-leaf class, we now define a mapping to the first/last member
// of the class, to allow efficient classof.
- NamedFirst = Field, NamedLast = ParmVar,
- FieldFirst = Field, FieldLast = ObjCIvar,
- ScopedFirst = Namespace, ScopedLast = ParmVar,
- TypeFirst = Typedef, TypeLast = Class,
- TagFirst = Enum , TagLast = Class,
- RecordFirst = Struct , RecordLast = Class,
- ValueFirst = EnumConstant , ValueLast = ParmVar,
- VarFirst = Var , VarLast = ParmVar
+ NamedFirst = Field , NamedLast = ParmVar,
+ FieldFirst = Field , FieldLast = ObjCIvar,
+ ScopedFirst = Namespace , ScopedLast = ParmVar,
+ TypeFirst = Typedef , TypeLast = CXXClass,
+ TagFirst = Enum , TagLast = CXXClass,
+ RecordFirst = Struct , RecordLast = CXXClass,
+ CXXRecordFirst = CXXStruct , CXXRecordLast = CXXClass,
+ ValueFirst = EnumConstant , ValueLast = ParmVar,
+ FunctionFirst = Function , FunctionLast = CXXMethod,
+ VarFirst = Var , VarLast = ParmVar
};
/// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
@@ -118,7 +130,13 @@
/// HasAttrs - This indicates whether the decl has attributes or not.
unsigned int HasAttrs : 1;
-protected:
+
+ protected:
+ /// Access - Used by C++ decls for the access specifier.
+ // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
+ unsigned Access : 2;
+ friend class CXXClassMemberWrapper;
+
Decl(Kind DK, SourceLocation L) : Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false) {
if (Decl::CollectingStats()) addDeclKind(DK);
@@ -161,10 +179,14 @@
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
+ case CXXField:
return IDNS_Ordinary;
case Struct:
case Union:
case Class:
+ case CXXStruct:
+ case CXXUnion:
+ case CXXClass:
case Enum:
return IDNS_Tag;
case Namespace:
@@ -206,8 +228,9 @@
/// TranslationUnitDecl
/// NamespaceDecl
/// FunctionDecl
-/// ObjCMethodDecl
+/// CXXRecordDecl
/// EnumDecl
+/// ObjCMethodDecl
/// ObjCInterfaceDecl
///
class DeclContext {
@@ -230,15 +253,18 @@
return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
case Decl::Namespace:
return static_cast<NamespaceDecl*>(const_cast<From*>(D));
- case Decl::Function:
- return static_cast<FunctionDecl*>(const_cast<From*>(D));
+ case Decl::Enum:
+ return static_cast<EnumDecl*>(const_cast<From*>(D));
case Decl::ObjCMethod:
return static_cast<ObjCMethodDecl*>(const_cast<From*>(D));
case Decl::ObjCInterface:
return static_cast<ObjCInterfaceDecl*>(const_cast<From*>(D));
- case Decl::Enum:
- return static_cast<EnumDecl*>(const_cast<From*>(D));
default:
+ if (DK >= Decl::FunctionFirst && DK <= Decl::FunctionLast)
+ return static_cast<FunctionDecl*>(const_cast<From*>(D));
+ if (DK >= Decl::CXXRecordFirst && DK <= Decl::CXXRecordLast)
+ return static_cast<CXXRecordDecl*>(const_cast<From*>(D));
+
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
@@ -255,6 +281,7 @@
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Function:
+ case Decl::CXXMethod:
case Decl::ObjCMethod:
return true;
default:
@@ -272,12 +299,17 @@
switch (D->getKind()) {
case Decl::TranslationUnit:
case Decl::Namespace:
- case Decl::Function:
+ case Decl::Enum:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
- case Decl::Enum:
return true;
default:
+ if (D->getKind() >= Decl::FunctionFirst &&
+ D->getKind() <= Decl::FunctionLast)
+ return true;
+ if (D->getKind() >= Decl::CXXRecordFirst &&
+ D->getKind() <= Decl::CXXRecordLast)
+ return true;
return false;
}
}
@@ -285,8 +317,9 @@
static bool classof(const TranslationUnitDecl *D) { return true; }
static bool classof(const NamespaceDecl *D) { return true; }
static bool classof(const FunctionDecl *D) { return true; }
- static bool classof(const ObjCMethodDecl *D) { return true; }
+ static bool classof(const CXXRecordDecl *D) { return true; }
static bool classof(const EnumDecl *D) { return true; }
+ static bool classof(const ObjCMethodDecl *D) { return true; }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
};
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
new file mode 100644
index 0000000..4c152f5
--- /dev/null
+++ b/include/clang/AST/DeclCXX.h
@@ -0,0 +1,195 @@
+//===-- DeclCXX.h - Classes for representing C++ declarations *- C++ -*-======//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the C++ Decl subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLCXX_H
+#define LLVM_CLANG_AST_DECLCXX_H
+
+#include "clang/AST/Decl.h"
+
+namespace clang {
+class CXXRecordDecl;
+
+/// CXXFieldDecl - Represents an instance field of a C++ struct/union/class.
+class CXXFieldDecl : public FieldDecl {
+ CXXRecordDecl *Parent;
+
+ CXXFieldDecl(CXXRecordDecl *RD, SourceLocation L, IdentifierInfo *Id,
+ QualType T, Expr *BW = NULL)
+ : FieldDecl(CXXField, L, Id, T, BW), Parent(RD) {}
+public:
+ static CXXFieldDecl *Create(ASTContext &C, CXXRecordDecl *RD,SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *BW = NULL);
+
+ void setAccess(AccessSpecifier AS) { Access = AS; }
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+ CXXRecordDecl *getParent() const { return Parent; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == CXXField; }
+ static bool classof(const CXXFieldDecl *D) { return true; }
+};
+
+/// CXXRecordDecl - Represents a C++ struct/union/class.
+/// The only difference with RecordDecl is that CXXRecordDecl is a DeclContext.
+class CXXRecordDecl : public RecordDecl, public DeclContext {
+protected:
+ CXXRecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ ScopedDecl *PrevDecl) : RecordDecl(DK, DC, L, Id, PrevDecl),
+ DeclContext(DK) {
+ assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
+ }
+public:
+ static CXXRecordDecl *Create(ASTContext &C, Kind DK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ ScopedDecl *PrevDecl);
+
+ const CXXFieldDecl *getMember(unsigned i) const {
+ return cast<const CXXFieldDecl>(RecordDecl::getMember(i));
+ }
+ CXXFieldDecl *getMember(unsigned i) {
+ return cast<CXXFieldDecl>(RecordDecl::getMember(i));
+ }
+
+ /// getMember - If the member doesn't exist, or there are no members, this
+ /// function will return 0;
+ CXXFieldDecl *getMember(IdentifierInfo *name) {
+ return cast_or_null<CXXFieldDecl>(RecordDecl::getMember(name));
+ }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() >= CXXRecordFirst && D->getKind() <= CXXRecordLast;
+ }
+ static bool classof(const CXXRecordDecl *D) { return true; }
+
+protected:
+ /// EmitImpl - Serialize this CXXRecordDecl. Called by Decl::Emit.
+ // FIXME: Implement this.
+ //virtual void EmitImpl(llvm::Serializer& S) const;
+
+ /// CreateImpl - Deserialize a CXXRecordDecl. Called by Decl::Create.
+ // FIXME: Implement this.
+ static CXXRecordDecl* CreateImpl(Kind DK, llvm::Deserializer& D, ASTContext& C);
+
+ friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
+/// CXXMethodDecl - Represents a static or instance method of a
+/// struct/union/class.
+class CXXMethodDecl : public FunctionDecl {
+
+ CXXMethodDecl(CXXRecordDecl *RD, SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ bool isStatic, bool isInline, ScopedDecl *PrevDecl)
+ : FunctionDecl(CXXMethod, RD, L, Id, T, (isStatic ? Static : None),
+ isInline, PrevDecl) {}
+public:
+ static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, bool isStatic = false,
+ bool isInline = false, ScopedDecl *PrevDecl = 0);
+
+ bool isStatic() const { return getStorageClass() == Static; }
+ bool isInstance() const { return !isStatic(); }
+
+ void setAccess(AccessSpecifier AS) { Access = AS; }
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ /// getThisType - Returns the type of 'this' pointer.
+ /// Should only be called for instance methods.
+ QualType getThisType(ASTContext &C) const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == CXXMethod; }
+ static bool classof(const CXXMethodDecl *D) { return true; }
+
+protected:
+ /// EmitImpl - Serialize this CXXMethodDecl. Called by Decl::Emit.
+ // FIXME: Implement this.
+ //virtual void EmitImpl(llvm::Serializer& S) const;
+
+ /// CreateImpl - Deserialize a CXXMethodDecl. Called by Decl::Create.
+ // FIXME: Implement this.
+ static CXXMethodDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+
+ friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
+/// CXXClassVarDecl - Represents a static data member of a struct/union/class.
+class CXXClassVarDecl : public VarDecl {
+
+ CXXClassVarDecl(CXXRecordDecl *RD, SourceLocation L,
+ IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl)
+ : VarDecl(CXXClassVar, RD, L, Id, T, None, PrevDecl) {}
+public:
+ static CXXClassVarDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L,IdentifierInfo *Id,
+ QualType T, ScopedDecl *PrevDecl);
+
+ void setAccess(AccessSpecifier AS) { Access = AS; }
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == CXXClassVar; }
+ static bool classof(const CXXClassVarDecl *D) { return true; }
+
+protected:
+ /// EmitImpl - Serialize this CXXClassVarDecl. Called by Decl::Emit.
+ // FIXME: Implement this.
+ //virtual void EmitImpl(llvm::Serializer& S) const;
+
+ /// CreateImpl - Deserialize a CXXClassVarDecl. Called by Decl::Create.
+ // FIXME: Implement this.
+ static CXXClassVarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+
+ friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
+
+/// CXXClassMemberWrapper - A wrapper class for C++ class member decls.
+/// Common functions like set/getAccess are included here to avoid bloating
+/// the interface of non-C++ specific decl classes, like NamedDecl.
+class CXXClassMemberWrapper {
+ Decl *MD;
+
+public:
+ CXXClassMemberWrapper(Decl *D) : MD(D) {
+ assert(isMember(D) && "Not a C++ class member!");
+ }
+
+ AccessSpecifier getAccess() const {
+ return AccessSpecifier(MD->Access);
+ }
+
+ void setAccess(AccessSpecifier AS) {
+ assert(AS != AS_none && "Access must be specified.");
+ MD->Access = AS;
+ }
+
+ CXXRecordDecl *getParent() const {
+ if (ScopedDecl *SD = dyn_cast<ScopedDecl>(MD)) {
+ return cast<CXXRecordDecl>(SD->getDeclContext());
+ }
+ return cast<CXXFieldDecl>(MD)->getParent();
+ }
+
+ static bool isMember(Decl *D) {
+ if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
+ return isa<CXXRecordDecl>(SD->getDeclContext());
+ }
+ return isa<CXXFieldDecl>(D);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 8d68a58..b5dba10 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -62,7 +62,7 @@
StorageClass S, bool isInline,
ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<FunctionDecl>();
- return new (Mem) FunctionDecl(DC, L, Id, T, S, isInline, PrevDecl);
+ return new (Mem) FunctionDecl(Function, DC, L, Id, T, S, isInline, PrevDecl);
}
FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index b5b0283..296304a 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/DenseMap.h"
using namespace clang;
@@ -206,6 +207,13 @@
case LinkageSpec: nLinkageSpecDecl++; break;
case FileScopeAsm: nFileScopeAsmDecl++; break;
case TranslationUnit: break;
+
+ // FIXME: Statistics for C++ decls.
+ case CXXField:
+ case CXXStruct: case CXXUnion: case CXXClass:
+ case CXXMethod:
+ case CXXClassVar:
+ break;
}
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
new file mode 100644
index 0000000..c319191
--- /dev/null
+++ b/lib/AST/DeclCXX.cpp
@@ -0,0 +1,58 @@
+//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++ related Decl classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ASTContext.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Decl Allocation/Deallocation Method Implementations
+//===----------------------------------------------------------------------===//
+
+CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, Expr *BW) {
+ void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
+ return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
+}
+
+CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, Kind DK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ ScopedDecl *PrevDecl) {
+ void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
+ return new (Mem) CXXRecordDecl(DK, DC, L, Id, PrevDecl);
+}
+
+CXXMethodDecl *
+CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, bool isStatic, bool isInline,
+ ScopedDecl *PrevDecl) {
+ void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
+ return new (Mem) CXXMethodDecl(RD, L, Id, T, isStatic, isInline, PrevDecl);
+}
+
+QualType CXXMethodDecl::getThisType(ASTContext &C) const {
+ assert(isInstance() && "No 'this' for static methods!");
+ QualType ClassTy = C.getTagDeclType(cast<CXXRecordDecl>(getParent()));
+ QualType ThisTy = C.getPointerType(ClassTy);
+ ThisTy.addConst();
+ return ThisTy;
+}
+
+CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, ScopedDecl *PrevDecl) {
+ void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
+ return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
+}
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index bbc28ab..ca9a152 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -384,7 +384,8 @@
void *Mem = C.getAllocator().Allocate<FunctionDecl>();
FunctionDecl* decl = new (Mem)
- FunctionDecl(0, SourceLocation(), NULL, QualType(), SClass, IsInline, 0);
+ FunctionDecl(Function, 0, SourceLocation(), NULL,
+ QualType(), SClass, IsInline, 0);
decl->ValueDecl::ReadInRec(D, C);
D.ReadPtr(decl->DeclChain);