diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 9092c3e0fa01f3139b016d05d267a89e3b07747a (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Frontend/PCHWriterDecl.cpp | |
parent | 4981926bf654fe5a2c3893f24ca44106b217e71e (diff) | |
download | FreeBSD-src-9092c3e0fa01f3139b016d05d267a89e3b07747a.zip FreeBSD-src-9092c3e0fa01f3139b016d05d267a89e3b07747a.tar.gz |
Update clang to r84119.
Diffstat (limited to 'lib/Frontend/PCHWriterDecl.cpp')
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 221 |
1 files changed, 184 insertions, 37 deletions
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index a6843e1..4527bb1 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -14,7 +14,10 @@ #include "clang/Frontend/PCHWriter.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" +#include "clang/AST/TypeLocVisitor.h" #include "llvm/Bitcode/BitstreamWriter.h" +#include <cstdio> + using namespace clang; //===----------------------------------------------------------------------===// @@ -32,8 +35,8 @@ namespace { pch::DeclCode Code; unsigned AbbrevToUse; - PCHDeclWriter(PCHWriter &Writer, ASTContext &Context, - PCHWriter::RecordData &Record) + PCHDeclWriter(PCHWriter &Writer, ASTContext &Context, + PCHWriter::RecordData &Record) : Writer(Writer), Context(Context), Record(Record) { } @@ -47,6 +50,7 @@ namespace { void VisitRecordDecl(RecordDecl *D); void VisitValueDecl(ValueDecl *D); void VisitEnumConstantDecl(EnumConstantDecl *D); + void VisitDeclaratorDecl(DeclaratorDecl *D); void VisitFunctionDecl(FunctionDecl *D); void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); @@ -55,7 +59,7 @@ namespace { void VisitOriginalParmVarDecl(OriginalParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitBlockDecl(BlockDecl *D); - void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, + void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, uint64_t VisibleOffset); void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCContainerDecl(ObjCContainerDecl *D); @@ -109,9 +113,12 @@ void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) { void PCHDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); + Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding Record.push_back(D->isDefinition()); Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); + Writer.AddSourceLocation(D->getRBraceLoc(), Record); + Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); } void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) { @@ -125,6 +132,7 @@ void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) { VisitTagDecl(D); Record.push_back(D->hasFlexibleArrayMember()); Record.push_back(D->isAnonymousStructOrUnion()); + Record.push_back(D->hasObjectMember()); Code = pch::DECL_RECORD; } @@ -141,22 +149,99 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { Writer.AddAPSInt(D->getInitVal(), Record); Code = pch::DECL_ENUM_CONSTANT; } +namespace { -void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { +class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { + PCHWriter &Writer; + PCHWriter::RecordData &Record; + +public: + TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) + : Writer(Writer), Record(Record) { } + +#define ABSTRACT_TYPELOC(CLASS) +#define TYPELOC(CLASS, PARENT, TYPE) \ + void Visit##CLASS(CLASS TyLoc); +#include "clang/AST/TypeLocNodes.def" + + void VisitTypeLoc(TypeLoc TyLoc) { + assert(0 && "A type loc wrapper was not handled!"); + } +}; + +} + +void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getStartLoc(), Record); +} +void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getNameLoc(), Record); +} +void TypeLocWriter::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getNameLoc(), Record); +} +void TypeLocWriter::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getLAngleLoc(), Record); + Writer.AddSourceLocation(TyLoc.getRAngleLoc(), Record); + for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i) + Writer.AddSourceLocation(TyLoc.getProtocolLoc(i), Record); +} +void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getStarLoc(), Record); +} +void TypeLocWriter::VisitBlockPointerLoc(BlockPointerLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getCaretLoc(), Record); +} +void TypeLocWriter::VisitMemberPointerLoc(MemberPointerLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getStarLoc(), Record); +} +void TypeLocWriter::VisitReferenceLoc(ReferenceLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getAmpLoc(), Record); +} +void TypeLocWriter::VisitFunctionLoc(FunctionLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getLParenLoc(), Record); + Writer.AddSourceLocation(TyLoc.getRParenLoc(), Record); + for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i) + Writer.AddDeclRef(TyLoc.getArg(i), Record); +} +void TypeLocWriter::VisitArrayLoc(ArrayLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getLBracketLoc(), Record); + Writer.AddSourceLocation(TyLoc.getRBracketLoc(), Record); + Record.push_back(TyLoc.getSizeExpr() ? 1 : 0); + if (TyLoc.getSizeExpr()) + Writer.AddStmt(TyLoc.getSizeExpr()); +} + +void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { VisitValueDecl(D); + DeclaratorInfo *DInfo = D->getDeclaratorInfo(); + if (DInfo == 0) { + Writer.AddTypeRef(QualType(), Record); + return; + } + + Writer.AddTypeRef(DInfo->getTypeLoc().getSourceType(), Record); + TypeLocWriter TLW(Writer, Record); + for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) + TLW.Visit(TL); +} + +void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { + VisitDeclaratorDecl(D); Record.push_back(D->isThisDeclarationADefinition()); if (D->isThisDeclarationADefinition()) Writer.AddStmt(D->getBody()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->isInline()); - Record.push_back(D->isC99InlineDefinition()); Record.push_back(D->isVirtualAsWritten()); Record.push_back(D->isPure()); Record.push_back(D->hasInheritedPrototype()); Record.push_back(D->hasWrittenPrototype()); Record.push_back(D->isDeleted()); - Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record); + Record.push_back(D->isTrivial()); + Record.push_back(D->isCopyAssignment()); + Record.push_back(D->hasImplicitReturnZero()); Writer.AddSourceLocation(D->getLocEnd(), Record); // FIXME: C++ TemplateOrInstantiation Record.push_back(D->param_size()); @@ -169,7 +254,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { VisitNamedDecl(D); // FIXME: convert to LazyStmtPtr? - // Unlike C/C++, method bodies will never be in header files. + // 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()); @@ -180,13 +265,13 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Record.push_back(D->isVariadic()); Record.push_back(D->isSynthesized()); // FIXME: stable encoding for @required/@optional - Record.push_back(D->getImplementationControl()); + Record.push_back(D->getImplementationControl()); // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway - Record.push_back(D->getObjCDeclQualifier()); + 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(), + for (ObjCMethodDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); P != PEnd; ++P) Writer.AddDeclRef(*P, Record); Code = pch::DECL_OBJC_METHOD; @@ -203,12 +288,12 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); Writer.AddDeclRef(D->getSuperClass(), Record); Record.push_back(D->protocol_size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), + for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), PEnd = D->protocol_end(); P != PEnd; ++P) Writer.AddDeclRef(*P, Record); Record.push_back(D->ivar_size()); - for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), + for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), IEnd = D->ivar_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Writer.AddDeclRef(D->getCategoryList(), Record); @@ -223,7 +308,7 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { VisitFieldDecl(D); // FIXME: stable encoding for @public/@private/@protected/@package - Record.push_back(D->getAccessControl()); + Record.push_back(D->getAccessControl()); Code = pch::DECL_OBJC_IVAR; } @@ -232,7 +317,7 @@ void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Record.push_back(D->isForwardDecl()); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Code = pch::DECL_OBJC_PROTOCOL; @@ -254,7 +339,7 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { VisitDecl(D); Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Code = pch::DECL_OBJC_FORWARD_PROTOCOL; @@ -264,7 +349,7 @@ void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { VisitObjCContainerDecl(D); Writer.AddDeclRef(D->getClassInterface(), Record); Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Writer.AddDeclRef(D->getNextClassCategory(), Record); @@ -294,9 +379,8 @@ void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitNamedDecl(D); + VisitObjCContainerDecl(D); Writer.AddDeclRef(D->getClassInterface(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); // Abstract class (no need to define a stable pch::DECL code). } @@ -321,7 +405,7 @@ void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { - VisitValueDecl(D); + VisitDeclaratorDecl(D); Record.push_back(D->isMutable()); Record.push_back(D->getBitWidth()? 1 : 0); if (D->getBitWidth()) @@ -330,13 +414,12 @@ void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { } void PCHDeclWriter::VisitVarDecl(VarDecl *D) { - VisitValueDecl(D); + VisitDeclaratorDecl(D); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->isThreadSpecified()); Record.push_back(D->hasCXXDirectInitializer()); Record.push_back(D->isDeclaredInCondition()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record); Record.push_back(D->getInit()? 1 : 0); if (D->getInit()) Writer.AddStmt(D->getInit()); @@ -351,16 +434,14 @@ void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { VisitVarDecl(D); Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding - // FIXME: emit default argument (C++) - // FIXME: why isn't the "default argument" just stored as the initializer - // in VarDecl? Code = pch::DECL_PARM_VAR; - - + + // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here // we dynamically check for the properties that we optimize for, but don't // know are true of all PARM_VAR_DECLs. - if (!D->hasAttrs() && + if (!D->getDeclaratorInfo() && + !D->hasAttrs() && !D->isImplicit() && !D->isUsed() && D->getAccess() == AS_none && @@ -413,7 +494,7 @@ void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) { /// that there are no declarations visible from this context. Note /// that this value will not be emitted for non-primary declaration /// contexts. -void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, +void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, uint64_t VisibleOffset) { Record.push_back(LexicalOffset); Record.push_back(VisibleOffset); @@ -439,26 +520,90 @@ void PCHWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - + // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // DeclaratorDecl + Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // StorageClass Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeSpecStartLoc Abv->Add(BitCodeAbbrevOp(0)); // HasInit // ParmVarDecl Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier - + ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv); } +/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by +/// consumers of the AST. +/// +/// Such decls will always be deserialized from the PCH file, so we would like +/// this to be as restrictive as possible. Currently the predicate is driven by +/// code generation requirements, if other clients have a different notion of +/// what is "required" then we may have to consider an alternate scheme where +/// clients can iterate over the top-level decls and get information on them, +/// without necessary deserializing them. We could explicitly require such +/// clients to use a separate API call to "realize" the decl. This should be +/// relatively painless since they would presumably only do it for top-level +/// decls. +// +// FIXME: This predicate is essentially IRgen's predicate to determine whether a +// declaration can be deferred. Merge them somehow. +static bool isRequiredDecl(const Decl *D, ASTContext &Context) { + // File scoped assembly must be seen. + if (isa<FileScopeAsmDecl>(D)) + return true; + + // Otherwise if this isn't a function or a file scoped variable it doesn't + // need to be seen. + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (!VD->isFileVarDecl()) + return false; + } else if (!isa<FunctionDecl>(D)) + return false; + + // Aliases and used decls must be seen. + if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>()) + return true; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // Forward declarations don't need to be seen. + if (!FD->isThisDeclarationADefinition()) + return false; + + // Constructors and destructors must be seen. + if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) + return true; + + // Otherwise, this is required unless it is static. + // + // FIXME: Inlines. + return FD->getStorageClass() != FunctionDecl::Static; + } else { + const VarDecl *VD = cast<VarDecl>(D); + + // In C++, this doesn't need to be seen if it is marked "extern". + if (Context.getLangOptions().CPlusPlus && !VD->getInit() && + (VD->getStorageClass() == VarDecl::Extern || + VD->isExternC())) + return false; + + // In C, this doesn't need to be seen unless it is a definition. + if (!Context.getLangOptions().CPlusPlus && !VD->getInit()) + return false; + + // Otherwise, this is required unless it is static. + return VD->getStorageClass() != VarDecl::Static; + } +} + /// \brief Write a block containing all of the declarations. void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // Enter the declarations block. @@ -466,7 +611,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // Output the abbreviations that we will use in this block. WriteDeclsBlockAbbrevs(); - + // Emit all of the declarations. RecordData Record; PCHDeclWriter W(*this, Context, Record); @@ -517,17 +662,19 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { exit(-1); } Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); - + // If the declaration had any attributes, write them now. if (D->hasAttrs()) WriteAttributeRecord(D->getAttrs()); // Flush any expressions that were written as part of this declaration. FlushStmts(); - - // Note external declarations so that we can add them to a record - // in the PCH file later. - if (isa<FileScopeAsmDecl>(D)) + + // Note "external" declarations so that we can add them to a record in the + // PCH file later. + // + // FIXME: This should be renamed, the predicate is much more complicated. + if (isRequiredDecl(D, Context)) ExternalDefinitions.push_back(ID); } |