//===--- DeclSerialization.cpp - Serialization of Decls ---------*- 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 methods that implement bitcode serialization for Decls. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "llvm/Bitcode/Serialize.h" #include "llvm/Bitcode/Deserialize.h" using llvm::Serializer; using llvm::Deserializer; using llvm::SerializedPtrID; using namespace clang; //===----------------------------------------------------------------------===// // Decl Serialization: Dispatch code to handle specialized decl types. //===----------------------------------------------------------------------===// void Decl::Emit(Serializer& S) const { S.EmitInt(getKind()); EmitImpl(S); S.Emit(getLocation()); S.EmitBool(InvalidDecl); // FIXME: HasAttrs? S.EmitBool(Implicit); S.EmitInt(Access); S.EmitPtr(cast_or_null(getDeclContext())); // From Decl. S.EmitPtr(cast_or_null(getLexicalDeclContext())); // From Decl. S.EmitPtr(NextDeclarator); if (const DeclContext *DC = dyn_cast(this)) DC->EmitOutRec(S); if (getDeclContext() && !getDeclContext()->isFunctionOrMethod()) { S.EmitBool(true); S.EmitOwnedPtr(NextDeclInScope); } else { S.EmitBool(false); S.EmitPtr(NextDeclInScope); } } Decl* Decl::Create(Deserializer& D, ASTContext& C) { Decl *Dcl; Kind k = static_cast(D.ReadInt()); switch (k) { default: assert (false && "Not implemented."); case TranslationUnit: Dcl = TranslationUnitDecl::CreateImpl(D, C); break; case Namespace: Dcl = NamespaceDecl::CreateImpl(D, C); break; case Var: Dcl = VarDecl::CreateImpl(D, C); break; case Enum: Dcl = EnumDecl::CreateImpl(D, C); break; case EnumConstant: Dcl = EnumConstantDecl::CreateImpl(D, C); break; case Field: Dcl = FieldDecl::CreateImpl(D, C); break; case ParmVar: Dcl = ParmVarDecl::CreateImpl(D, C); break; case OriginalParmVar: Dcl = OriginalParmVarDecl::CreateImpl(D, C); break; case Function: Dcl = FunctionDecl::CreateImpl(D, C); break; case OverloadedFunction: Dcl = OverloadedFunctionDecl::CreateImpl(D, C); break; case Record: Dcl = RecordDecl::CreateImpl(D, C); break; case Typedef: Dcl = TypedefDecl::CreateImpl(D, C); break; case TemplateTypeParm: Dcl = TemplateTypeParmDecl::CreateImpl(D, C); break; case FileScopeAsm: Dcl = FileScopeAsmDecl::CreateImpl(D, C); break; } Dcl->Loc = SourceLocation::ReadVal(D); // From Decl. Dcl->InvalidDecl = D.ReadBool(); // FIXME: HasAttrs? Dcl->Implicit = D.ReadBool(); Dcl->Access = D.ReadInt(); assert(Dcl->DeclCtx == 0); const SerializedPtrID &SemaDCPtrID = D.ReadPtrID(); const SerializedPtrID &LexicalDCPtrID = D.ReadPtrID(); if (SemaDCPtrID == LexicalDCPtrID) { // Allow back-patching. Observe that we register the variable of the // *object* for back-patching. Its actual value will get filled in later. D.ReadUIntPtr(Dcl->DeclCtx, SemaDCPtrID); } else { MultipleDC *MDC = new MultipleDC(); Dcl->DeclCtx = reinterpret_cast(MDC) | 0x1; // Allow back-patching. Observe that we register the variable of the // *object* for back-patching. Its actual value will get filled in later. D.ReadPtr(MDC->SemanticDC, SemaDCPtrID); D.ReadPtr(MDC->LexicalDC, LexicalDCPtrID); } D.ReadPtr(Dcl->NextDeclarator); if (DeclContext *DC = dyn_cast(Dcl)) DC->ReadOutRec(D, C); bool OwnsNext = D.ReadBool(); if (OwnsNext) Dcl->NextDeclInScope = D.ReadOwnedPtr(C); else D.ReadPtr(Dcl->NextDeclInScope); return Dcl; } //===----------------------------------------------------------------------===// // Common serialization logic for subclasses of DeclContext. //===----------------------------------------------------------------------===// void DeclContext::EmitOutRec(Serializer& S) const { bool Owned = !isFunctionOrMethod(); S.EmitBool(Owned); if (Owned) S.EmitOwnedPtr(FirstDecl); else S.EmitPtr(FirstDecl); S.EmitPtr(LastDecl); } void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) { bool Owned = D.ReadBool(); if (Owned) FirstDecl = cast_or_null(D.ReadOwnedPtr(C)); else D.ReadPtr(FirstDecl); D.ReadPtr(LastDecl); } //===----------------------------------------------------------------------===// // Common serialization logic for subclasses of NamedDecl. //===----------------------------------------------------------------------===// void NamedDecl::EmitInRec(Serializer& S) const { S.EmitInt(Name.getNameKind()); switch (Name.getNameKind()) { case DeclarationName::Identifier: S.EmitPtr(Name.getAsIdentifierInfo()); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: Name.getObjCSelector().Emit(S); break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: Name.getCXXNameType().Emit(S); break; case DeclarationName::CXXOperatorName: S.EmitInt(Name.getCXXOverloadedOperator()); break; case DeclarationName::CXXUsingDirective: // No extra data to emit break; } } void NamedDecl::ReadInRec(Deserializer& D, ASTContext& C) { DeclarationName::NameKind Kind = static_cast(D.ReadInt()); switch (Kind) { case DeclarationName::Identifier: { // Don't allow back-patching. The IdentifierInfo table must already // be loaded. Name = D.ReadPtr(); break; } case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: Name = Selector::ReadVal(D); break; case DeclarationName::CXXConstructorName: Name = C.DeclarationNames.getCXXConstructorName(QualType::ReadVal(D)); break; case DeclarationName::CXXDestructorName: Name = C.DeclarationNames.getCXXDestructorName(QualType::ReadVal(D)); break; case DeclarationName::CXXConversionFunctionName: Name = C.DeclarationNames.getCXXConversionFunctionName(QualType::ReadVal(D)); break; case DeclarationName::CXXOperatorName: { OverloadedOperatorKind Op = static_cast(D.ReadInt()); Name = C.DeclarationNames.getCXXOperatorName(Op); break; } case DeclarationName::CXXUsingDirective: Name = DeclarationName::getUsingDirectiveName(); break; } } //===----------------------------------------------------------------------===// // Common serialization logic for subclasses of ValueDecl. //===----------------------------------------------------------------------===// void ValueDecl::EmitInRec(Serializer& S) const { NamedDecl::EmitInRec(S); S.Emit(getType()); // From ValueDecl. } void ValueDecl::ReadInRec(Deserializer& D, ASTContext& C) { NamedDecl::ReadInRec(D, C); DeclType = QualType::ReadVal(D); // From ValueDecl. } //===----------------------------------------------------------------------===// // Common serialization logic for subclasses of VarDecl. //===----------------------------------------------------------------------===// void VarDecl::EmitInRec(Serializer& S) const { ValueDecl::EmitInRec(S); S.EmitInt(getStorageClass()); // From VarDecl. } void VarDecl::ReadInRec(Deserializer& D, ASTContext& C) { ValueDecl::ReadInRec(D, C); SClass = static_cast(D.ReadInt()); // From VarDecl. } void VarDecl::EmitOutRec(Serializer& S) const { // Emit this last because it will create a record of its own. S.EmitOwnedPtr(getInit()); } void VarDecl::ReadOutRec(Deserializer& D, ASTContext& C) { Init = D.ReadOwnedPtr(C); } void VarDecl::EmitImpl(Serializer& S) const { VarDecl::EmitInRec(S); VarDecl::EmitOutRec(S); } void VarDecl::ReadImpl(Deserializer& D, ASTContext& C) { ReadInRec(D, C); ReadOutRec(D, C); } //===----------------------------------------------------------------------===// // TranslationUnitDecl Serialization. //===----------------------------------------------------------------------===// void TranslationUnitDecl::EmitImpl(llvm::Serializer& S) const { } TranslationUnitDecl* TranslationUnitDecl::CreateImpl(Deserializer& D, ASTContext& C) { return new (C) TranslationUnitDecl(); } //===----------------------------------------------------------------------===// // NamespaceDecl Serialization. //===----------------------------------------------------------------------===// void NamespaceDecl::EmitImpl(llvm::Serializer& S) const { NamedDecl::EmitInRec(S); S.Emit(getLBracLoc()); S.Emit(getRBracLoc()); } NamespaceDecl* NamespaceDecl::CreateImpl(Deserializer& D, ASTContext& C) { NamespaceDecl* decl = new (C) NamespaceDecl(0, SourceLocation(), 0); decl->NamedDecl::ReadInRec(D, C); decl->LBracLoc = SourceLocation::ReadVal(D); decl->RBracLoc = SourceLocation::ReadVal(D); return decl; } //===----------------------------------------------------------------------===// // VarDecl Serialization. //===----------------------------------------------------------------------===// VarDecl* VarDecl::CreateImpl(Deserializer& D, ASTContext& C) { VarDecl* decl = new (C) VarDecl(Var, 0, SourceLocation(), NULL, QualType(), None); decl->VarDecl::ReadImpl(D, C); return decl; } //===----------------------------------------------------------------------===// // ParmVarDecl Serialization. //===----------------------------------------------------------------------===// void ParmVarDecl::EmitImpl(llvm::Serializer& S) const { VarDecl::EmitImpl(S); S.EmitInt(getObjCDeclQualifier()); // From ParmVarDecl. S.EmitOwnedPtr(getDefaultArg()); // From ParmVarDecl. } ParmVarDecl* ParmVarDecl::CreateImpl(Deserializer& D, ASTContext& C) { ParmVarDecl* decl = new (C) ParmVarDecl(ParmVar, 0, SourceLocation(), NULL, QualType(), None, NULL); decl->VarDecl::ReadImpl(D, C); decl->objcDeclQualifier = static_cast(D.ReadInt()); decl->DefaultArg = D.ReadOwnedPtr(C); return decl; } //===----------------------------------------------------------------------===// // OriginalParmVarDecl Serialization. //===----------------------------------------------------------------------===// void OriginalParmVarDecl::EmitImpl(llvm::Serializer& S) const { ParmVarDecl::EmitImpl(S); S.Emit(OriginalType); } OriginalParmVarDecl* OriginalParmVarDecl::CreateImpl( Deserializer& D, ASTContext& C) { OriginalParmVarDecl* decl = new (C) OriginalParmVarDecl(0, SourceLocation(), NULL, QualType(), QualType(), None, NULL); decl->ParmVarDecl::ReadImpl(D, C); decl->OriginalType = QualType::ReadVal(D); return decl; } //===----------------------------------------------------------------------===// // EnumDecl Serialization. //===----------------------------------------------------------------------===// void EnumDecl::EmitImpl(Serializer& S) const { NamedDecl::EmitInRec(S); S.EmitBool(isDefinition()); S.Emit(IntegerType); } EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) { EnumDecl* decl = new (C) EnumDecl(0, SourceLocation(), NULL); decl->NamedDecl::ReadInRec(D, C); decl->setDefinition(D.ReadBool()); decl->IntegerType = QualType::ReadVal(D); return decl; } //===----------------------------------------------------------------------===// // EnumConstantDecl Serialization. //===----------------------------------------------------------------------===// void EnumConstantDecl::EmitImpl(Serializer& S) const { S.Emit(Val); ValueDecl::EmitInRec(S); S.EmitOwnedPtr(Init); } EnumConstantDecl* EnumConstantDecl::CreateImpl(Deserializer& D, ASTContext& C) { llvm::APSInt val(1); D.Read(val); EnumConstantDecl* decl = new (C) EnumConstantDecl(0, SourceLocation(), NULL, QualType(), NULL, val); decl->ValueDecl::ReadInRec(D, C); decl->Init = D.ReadOwnedPtr(C); return decl; } //===----------------------------------------------------------------------===// // FieldDecl Serialization. //===----------------------------------------------------------------------===// void FieldDecl::EmitImpl(Serializer& S) const { S.EmitBool(Mutable); S.Emit(getType()); ValueDecl::EmitInRec(S); S.EmitOwnedPtr(BitWidth); } FieldDecl* FieldDecl::CreateImpl(Deserializer& D, ASTContext& C) { FieldDecl* decl = new (C) FieldDecl(Field, 0, SourceLocation(), NULL, QualType(), 0, false); decl->Mutable = D.ReadBool(); decl->ValueDecl::ReadInRec(D, C); decl->BitWidth = D.ReadOwnedPtr(C); return decl; } //===----------------------------------------------------------------------===// // FunctionDecl Serialization. //===----------------------------------------------------------------------===// void FunctionDecl::EmitImpl(Serializer& S) const { S.EmitInt(SClass); // From FunctionDecl. S.EmitBool(IsInline); // From FunctionDecl. ValueDecl::EmitInRec(S); S.EmitPtr(PreviousDeclaration); // NOTE: We do not need to serialize out the number of parameters, because // that is encoded in the type (accessed via getNumParams()). if (ParamInfo != NULL) { S.EmitBool(true); S.EmitInt(getNumParams()); S.BatchEmitOwnedPtrs(getNumParams(),&ParamInfo[0], Body); } else { S.EmitBool(false); S.EmitOwnedPtr(Body); } } FunctionDecl* FunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) { StorageClass SClass = static_cast(D.ReadInt()); bool IsInline = D.ReadBool(); FunctionDecl* decl = new (C) FunctionDecl(Function, 0, SourceLocation(), DeclarationName(), QualType(), SClass, IsInline); decl->ValueDecl::ReadInRec(D, C); D.ReadPtr(decl->PreviousDeclaration); int numParams = 0; bool hasParamDecls = D.ReadBool(); if (hasParamDecls) numParams = D.ReadInt(); decl->ParamInfo = hasParamDecls ? new ParmVarDecl*[numParams] : NULL; if (hasParamDecls) D.BatchReadOwnedPtrs(numParams, reinterpret_cast(&decl->ParamInfo[0]), decl->Body, C); else decl->Body = D.ReadOwnedPtr(C); return decl; } void BlockDecl::EmitImpl(Serializer& S) const { // FIXME: what about arguments? S.Emit(getCaretLocation()); S.EmitOwnedPtr(Body); } BlockDecl* BlockDecl::CreateImpl(Deserializer& D, ASTContext& C) { QualType Q = QualType::ReadVal(D); SourceLocation L = SourceLocation::ReadVal(D); /*CompoundStmt* BodyStmt = cast(*/D.ReadOwnedPtr(C)/*)*/; assert(0 && "Cannot deserialize BlockBlockExpr yet"); // FIXME: need to handle parameters. //return new BlockBlockExpr(L, Q, BodyStmt); return 0; } //===----------------------------------------------------------------------===// // OverloadedFunctionDecl Serialization. //===----------------------------------------------------------------------===// void OverloadedFunctionDecl::EmitImpl(Serializer& S) const { NamedDecl::EmitInRec(S); S.EmitInt(getNumFunctions()); for (unsigned func = 0; func < getNumFunctions(); ++func) S.EmitPtr(Functions[func]); } OverloadedFunctionDecl * OverloadedFunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) { OverloadedFunctionDecl* decl = new (C) OverloadedFunctionDecl(0, DeclarationName()); decl->NamedDecl::ReadInRec(D, C); unsigned numFunctions = D.ReadInt(); decl->Functions.reserve(numFunctions); for (unsigned func = 0; func < numFunctions; ++func) D.ReadPtr(decl->Functions[func]); return decl; } //===----------------------------------------------------------------------===// // RecordDecl Serialization. //===----------------------------------------------------------------------===// void RecordDecl::EmitImpl(Serializer& S) const { S.EmitInt(getTagKind()); NamedDecl::EmitInRec(S); S.EmitBool(isDefinition()); S.EmitBool(hasFlexibleArrayMember()); S.EmitBool(isAnonymousStructOrUnion()); } RecordDecl* RecordDecl::CreateImpl(Deserializer& D, ASTContext& C) { TagKind TK = TagKind(D.ReadInt()); RecordDecl* decl = new (C) RecordDecl(Record, TK, 0, SourceLocation(), NULL); decl->NamedDecl::ReadInRec(D, C); decl->setDefinition(D.ReadBool()); decl->setHasFlexibleArrayMember(D.ReadBool()); decl->setAnonymousStructOrUnion(D.ReadBool()); return decl; } //===----------------------------------------------------------------------===// // TypedefDecl Serialization. //===----------------------------------------------------------------------===// void TypedefDecl::EmitImpl(Serializer& S) const { S.Emit(UnderlyingType); NamedDecl::EmitInRec(S); } TypedefDecl* TypedefDecl::CreateImpl(Deserializer& D, ASTContext& C) { QualType T = QualType::ReadVal(D); TypedefDecl* decl = new (C) TypedefDecl(0, SourceLocation(), NULL, T); decl->NamedDecl::ReadInRec(D, C); return decl; } //===----------------------------------------------------------------------===// // TemplateTypeParmDecl Serialization. //===----------------------------------------------------------------------===// void TemplateTypeParmDecl::EmitImpl(Serializer& S) const { S.EmitBool(Typename); TypeDecl::EmitInRec(S); } TemplateTypeParmDecl * TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { bool Typename = D.ReadBool(); TemplateTypeParmDecl *decl = new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, Typename, QualType()); decl->TypeDecl::ReadInRec(D, C); return decl; } //===----------------------------------------------------------------------===// // NonTypeTemplateParmDecl Serialization. //===----------------------------------------------------------------------===// void NonTypeTemplateParmDecl::EmitImpl(Serializer& S) const { S.EmitInt(Depth); S.EmitInt(Position); NamedDecl::Emit(S); } NonTypeTemplateParmDecl* NonTypeTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { unsigned Depth = D.ReadInt(); unsigned Position = D.ReadInt(); NonTypeTemplateParmDecl *decl = new (C) NonTypeTemplateParmDecl(0, SourceLocation(), Depth, Position, 0, QualType(), SourceLocation()); decl->NamedDecl::ReadInRec(D, C); return decl; } //===----------------------------------------------------------------------===// // TemplateTemplateParmDecl Serialization. //===----------------------------------------------------------------------===// void TemplateTemplateParmDecl::EmitImpl(Serializer& S) const { S.EmitInt(Depth); S.EmitInt(Position); NamedDecl::EmitInRec(S); } TemplateTemplateParmDecl* TemplateTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { unsigned Depth = D.ReadInt(); unsigned Position = D.ReadInt(); TemplateTemplateParmDecl *decl = new (C) TemplateTemplateParmDecl(0, SourceLocation(), Depth, Position, 0, 0); decl->NamedDecl::ReadInRec(D, C); return decl; } //===----------------------------------------------------------------------===// // LinkageSpec Serialization. //===----------------------------------------------------------------------===// void LinkageSpecDecl::EmitInRec(Serializer& S) const { S.EmitInt(getLanguage()); S.EmitBool(HadBraces); } void LinkageSpecDecl::ReadInRec(Deserializer& D, ASTContext& C) { Language = static_cast(D.ReadInt()); HadBraces = D.ReadBool(); } //===----------------------------------------------------------------------===// // FileScopeAsm Serialization. //===----------------------------------------------------------------------===// void FileScopeAsmDecl::EmitImpl(llvm::Serializer& S) const { S.EmitOwnedPtr(AsmString); } FileScopeAsmDecl* FileScopeAsmDecl::CreateImpl(Deserializer& D, ASTContext& C) { FileScopeAsmDecl* decl = new (C) FileScopeAsmDecl(0, SourceLocation(), 0); decl->AsmString = cast(D.ReadOwnedPtr(C)); // D.ReadOwnedPtr(D.ReadOwnedPtr())<#T * * Ptr#>, <#bool AutoRegister#>)(decl->AsmString); return decl; }