2010-08-19 07:57:11 +08:00
|
|
|
//===--- ASTReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
|
2009-04-27 13:27:42 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2010-08-19 07:56:43 +08:00
|
|
|
// This file implements the ASTReader::ReadDeclRecord method, which is the
|
2009-04-27 13:27:42 +08:00
|
|
|
// entrypoint for loading a decl.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Serialization/ASTReader.h"
|
2010-10-25 01:26:36 +08:00
|
|
|
#include "ASTCommon.h"
|
2012-04-15 20:36:49 +08:00
|
|
|
#include "ASTReaderInternals.h"
|
2009-04-27 13:27:42 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-05-08 05:43:38 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/DeclGroup.h"
|
2010-05-08 05:43:38 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/DeclVisitor.h"
|
2009-04-27 13:27:42 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/IdentifierResolver.h"
|
|
|
|
#include "clang/Sema/Sema.h"
|
|
|
|
#include "clang/Sema/SemaDiagnostic.h"
|
2012-05-04 09:49:36 +08:00
|
|
|
#include "llvm/Support/SaveAndRestore.h"
|
2009-04-27 13:27:42 +08:00
|
|
|
using namespace clang;
|
2010-08-19 07:57:32 +08:00
|
|
|
using namespace clang::serialization;
|
2009-04-27 13:27:42 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Declaration deserialization
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-06-30 06:47:00 +08:00
|
|
|
namespace clang {
|
2010-08-19 07:56:48 +08:00
|
|
|
class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
|
2010-08-19 07:56:43 +08:00
|
|
|
ASTReader &Reader;
|
2011-12-01 07:21:26 +08:00
|
|
|
ModuleFile &F;
|
2010-08-19 07:57:32 +08:00
|
|
|
const DeclID ThisDeclID;
|
2011-10-28 02:47:35 +08:00
|
|
|
const unsigned RawLocation;
|
2010-10-25 01:26:27 +08:00
|
|
|
typedef ASTReader::RecordData RecordData;
|
|
|
|
const RecordData &Record;
|
2009-04-27 13:27:42 +08:00
|
|
|
unsigned &Idx;
|
2010-08-19 07:57:32 +08:00
|
|
|
TypeID TypeIDForTypeDecl;
|
2011-03-05 09:35:54 +08:00
|
|
|
|
2012-10-10 01:21:28 +08:00
|
|
|
bool HasPendingBody;
|
|
|
|
|
2010-07-23 06:43:28 +08:00
|
|
|
uint64_t GetCurrentCursorOffset();
|
2011-07-22 06:35:25 +08:00
|
|
|
|
2010-10-25 01:26:27 +08:00
|
|
|
SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) {
|
2010-10-05 23:59:54 +08:00
|
|
|
return Reader.ReadSourceLocation(F, R, I);
|
|
|
|
}
|
2011-07-22 06:35:25 +08:00
|
|
|
|
2010-10-25 01:26:27 +08:00
|
|
|
SourceRange ReadSourceRange(const RecordData &R, unsigned &I) {
|
2010-10-05 23:59:54 +08:00
|
|
|
return Reader.ReadSourceRange(F, R, I);
|
|
|
|
}
|
2011-07-22 06:35:25 +08:00
|
|
|
|
2010-10-25 01:26:27 +08:00
|
|
|
TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) {
|
2010-10-05 23:59:54 +08:00
|
|
|
return Reader.GetTypeSourceInfo(F, R, I);
|
|
|
|
}
|
2011-07-22 06:35:25 +08:00
|
|
|
|
|
|
|
serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {
|
|
|
|
return Reader.ReadDeclID(F, R, I);
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl *ReadDecl(const RecordData &R, unsigned &I) {
|
|
|
|
return Reader.ReadDecl(F, R, I);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T *ReadDeclAs(const RecordData &R, unsigned &I) {
|
|
|
|
return Reader.ReadDeclAs<T>(F, R, I);
|
|
|
|
}
|
|
|
|
|
2010-10-16 02:21:24 +08:00
|
|
|
void ReadQualifierInfo(QualifierInfo &Info,
|
2010-10-25 01:26:27 +08:00
|
|
|
const RecordData &R, unsigned &I) {
|
2010-10-16 02:21:24 +08:00
|
|
|
Reader.ReadQualifierInfo(F, Info, R, I);
|
|
|
|
}
|
2011-07-22 06:35:25 +08:00
|
|
|
|
2010-10-16 02:21:24 +08:00
|
|
|
void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name,
|
2010-10-25 01:26:27 +08:00
|
|
|
const RecordData &R, unsigned &I) {
|
2010-10-16 02:21:24 +08:00
|
|
|
Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I);
|
|
|
|
}
|
2011-07-22 06:35:25 +08:00
|
|
|
|
2010-10-16 02:21:24 +08:00
|
|
|
void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo,
|
2010-10-25 01:26:27 +08:00
|
|
|
const RecordData &R, unsigned &I) {
|
2010-10-16 02:21:24 +08:00
|
|
|
Reader.ReadDeclarationNameInfo(F, NameInfo, R, I);
|
|
|
|
}
|
2010-07-23 06:43:28 +08:00
|
|
|
|
2011-12-02 06:20:10 +08:00
|
|
|
serialization::SubmoduleID readSubmoduleID(const RecordData &R,
|
|
|
|
unsigned &I) {
|
|
|
|
if (I >= R.size())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Reader.getGlobalSubmoduleID(F, R[I++]);
|
|
|
|
}
|
|
|
|
|
2011-12-03 07:23:56 +08:00
|
|
|
Module *readModule(const RecordData &R, unsigned &I) {
|
|
|
|
return Reader.getSubmodule(readSubmoduleID(R, I));
|
|
|
|
}
|
|
|
|
|
2010-10-25 01:26:40 +08:00
|
|
|
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
|
|
|
|
const RecordData &R, unsigned &I);
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
/// \brief RAII class used to capture the first ID within a redeclaration
|
|
|
|
/// chain and to introduce it into the list of pending redeclaration chains
|
|
|
|
/// on destruction.
|
|
|
|
///
|
|
|
|
/// The caller can choose not to introduce this ID into the redeclaration
|
|
|
|
/// chain by calling \c suppress().
|
|
|
|
class RedeclarableResult {
|
|
|
|
ASTReader &Reader;
|
|
|
|
GlobalDeclID FirstID;
|
|
|
|
mutable bool Owning;
|
2013-01-22 00:16:40 +08:00
|
|
|
Decl::Kind DeclKind;
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-09-16 04:20:27 +08:00
|
|
|
void operator=(RedeclarableResult &) LLVM_DELETED_FUNCTION;
|
2011-12-22 09:48:48 +08:00
|
|
|
|
|
|
|
public:
|
2013-01-22 00:16:40 +08:00
|
|
|
RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
|
|
|
|
Decl::Kind DeclKind)
|
|
|
|
: Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { }
|
2011-12-22 09:48:48 +08:00
|
|
|
|
|
|
|
RedeclarableResult(const RedeclarableResult &Other)
|
2013-01-22 00:16:40 +08:00
|
|
|
: Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) ,
|
|
|
|
DeclKind(Other.DeclKind)
|
2011-12-22 09:48:48 +08:00
|
|
|
{
|
|
|
|
Other.Owning = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
~RedeclarableResult() {
|
2013-01-22 00:16:40 +08:00
|
|
|
if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) &&
|
|
|
|
Reader.PendingDeclChainsKnown.insert(FirstID))
|
2011-12-22 09:48:48 +08:00
|
|
|
Reader.PendingDeclChains.push_back(FirstID);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the first ID.
|
|
|
|
GlobalDeclID getFirstID() const { return FirstID; }
|
|
|
|
|
|
|
|
/// \brief Do not introduce this declaration ID into the set of pending
|
|
|
|
/// declaration chains.
|
|
|
|
void suppress() {
|
|
|
|
Owning = false;
|
|
|
|
}
|
|
|
|
};
|
2013-01-22 00:16:40 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
/// \brief Class used to capture the result of searching for an existing
|
|
|
|
/// declaration of a specific kind and name, along with the ability
|
|
|
|
/// to update the place where this result was found (the declaration
|
|
|
|
/// chain hanging off an identifier or the DeclContext we searched in)
|
|
|
|
/// if requested.
|
|
|
|
class FindExistingResult {
|
|
|
|
ASTReader &Reader;
|
|
|
|
NamedDecl *New;
|
|
|
|
NamedDecl *Existing;
|
|
|
|
mutable bool AddResult;
|
|
|
|
|
2012-09-16 04:20:27 +08:00
|
|
|
void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION;
|
2011-12-22 09:48:48 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
FindExistingResult(ASTReader &Reader)
|
|
|
|
: Reader(Reader), New(0), Existing(0), AddResult(false) { }
|
|
|
|
|
|
|
|
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing)
|
|
|
|
: Reader(Reader), New(New), Existing(Existing), AddResult(true) { }
|
|
|
|
|
|
|
|
FindExistingResult(const FindExistingResult &Other)
|
|
|
|
: Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
|
|
|
|
AddResult(Other.AddResult)
|
|
|
|
{
|
|
|
|
Other.AddResult = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
~FindExistingResult();
|
|
|
|
|
2012-01-04 06:46:00 +08:00
|
|
|
/// \brief Suppress the addition of this result into the known set of
|
|
|
|
/// names.
|
|
|
|
void suppress() { AddResult = false; }
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
operator NamedDecl*() const { return Existing; }
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
operator T*() const { return dyn_cast_or_null<T>(Existing); }
|
|
|
|
};
|
|
|
|
|
|
|
|
FindExistingResult findExisting(NamedDecl *D);
|
|
|
|
|
2009-04-27 13:27:42 +08:00
|
|
|
public:
|
2011-12-01 07:21:26 +08:00
|
|
|
ASTDeclReader(ASTReader &Reader, ModuleFile &F,
|
2012-09-18 13:34:55 +08:00
|
|
|
DeclID thisDeclID,
|
2011-10-28 02:47:35 +08:00
|
|
|
unsigned RawLocation,
|
2010-10-25 01:26:27 +08:00
|
|
|
const RecordData &Record, unsigned &Idx)
|
2012-09-18 13:34:55 +08:00
|
|
|
: Reader(Reader), F(F), ThisDeclID(thisDeclID),
|
2011-10-28 02:47:35 +08:00
|
|
|
RawLocation(RawLocation), Record(Record), Idx(Idx),
|
2012-10-10 01:21:28 +08:00
|
|
|
TypeIDForTypeDecl(0), HasPendingBody(false) { }
|
2009-04-27 13:27:42 +08:00
|
|
|
|
2011-02-12 15:50:47 +08:00
|
|
|
static void attachPreviousDecl(Decl *D, Decl *previous);
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
static void attachLatestDecl(Decl *D, Decl *latest);
|
2011-02-12 15:50:47 +08:00
|
|
|
|
2012-10-10 01:21:28 +08:00
|
|
|
/// \brief Determine whether this declaration has a pending body.
|
|
|
|
bool hasPendingBody() const { return HasPendingBody; }
|
|
|
|
|
2010-07-02 19:55:01 +08:00
|
|
|
void Visit(Decl *D);
|
|
|
|
|
2011-12-01 07:21:26 +08:00
|
|
|
void UpdateDecl(Decl *D, ModuleFile &ModuleFile,
|
2011-04-29 16:19:30 +08:00
|
|
|
const RecordData &Record);
|
2010-10-25 01:26:36 +08:00
|
|
|
|
2011-09-01 08:58:55 +08:00
|
|
|
static void setNextObjCCategory(ObjCCategoryDecl *Cat,
|
|
|
|
ObjCCategoryDecl *Next) {
|
|
|
|
Cat->NextClassCategory = Next;
|
|
|
|
}
|
|
|
|
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitDecl(Decl *D);
|
|
|
|
void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
|
|
|
|
void VisitNamedDecl(NamedDecl *ND);
|
2011-02-17 15:39:24 +08:00
|
|
|
void VisitLabelDecl(LabelDecl *LD);
|
2010-02-22 02:22:14 +08:00
|
|
|
void VisitNamespaceDecl(NamespaceDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
|
|
|
|
void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitTypeDecl(TypeDecl *TD);
|
2011-12-19 22:40:25 +08:00
|
|
|
void VisitTypedefNameDecl(TypedefNameDecl *TD);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitTypedefDecl(TypedefDecl *TD);
|
2011-04-15 22:24:37 +08:00
|
|
|
void VisitTypeAliasDecl(TypeAliasDecl *TD);
|
2010-06-30 16:49:30 +08:00
|
|
|
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
|
2013-05-23 09:49:11 +08:00
|
|
|
RedeclarableResult VisitTagDecl(TagDecl *TD);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitEnumDecl(EnumDecl *ED);
|
2013-05-23 09:49:11 +08:00
|
|
|
RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
|
|
|
|
void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); }
|
|
|
|
RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D);
|
|
|
|
void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
|
|
|
|
RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
|
2010-05-08 05:43:38 +08:00
|
|
|
ClassTemplateSpecializationDecl *D);
|
2013-05-23 09:49:11 +08:00
|
|
|
void VisitClassTemplateSpecializationDecl(
|
|
|
|
ClassTemplateSpecializationDecl *D) {
|
|
|
|
VisitClassTemplateSpecializationDeclImpl(D);
|
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitClassTemplatePartialSpecializationDecl(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D);
|
2011-08-31 21:59:56 +08:00
|
|
|
void VisitClassScopeFunctionSpecializationDecl(
|
|
|
|
ClassScopeFunctionSpecializationDecl *D);
|
2013-08-06 09:03:05 +08:00
|
|
|
RedeclarableResult
|
|
|
|
VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);
|
|
|
|
void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
|
|
|
|
VisitVarTemplateSpecializationDeclImpl(D);
|
|
|
|
}
|
|
|
|
void VisitVarTemplatePartialSpecializationDecl(
|
|
|
|
VarTemplatePartialSpecializationDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitValueDecl(ValueDecl *VD);
|
|
|
|
void VisitEnumConstantDecl(EnumConstantDecl *ECD);
|
2010-06-30 16:49:30 +08:00
|
|
|
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
2009-08-19 09:28:35 +08:00
|
|
|
void VisitDeclaratorDecl(DeclaratorDecl *DD);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitFunctionDecl(FunctionDecl *FD);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitCXXMethodDecl(CXXMethodDecl *D);
|
|
|
|
void VisitCXXConstructorDecl(CXXConstructorDecl *D);
|
|
|
|
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
|
|
|
|
void VisitCXXConversionDecl(CXXConversionDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitFieldDecl(FieldDecl *FD);
|
2013-04-16 15:28:30 +08:00
|
|
|
void VisitMSPropertyDecl(MSPropertyDecl *FD);
|
2010-11-21 14:08:52 +08:00
|
|
|
void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
|
2013-08-06 09:03:05 +08:00
|
|
|
RedeclarableResult VisitVarDeclImpl(VarDecl *D);
|
|
|
|
void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); }
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
|
|
|
|
void VisitParmVarDecl(ParmVarDecl *PD);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
|
|
|
|
void VisitTemplateDecl(TemplateDecl *D);
|
2012-01-07 06:05:37 +08:00
|
|
|
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
2013-08-06 09:03:05 +08:00
|
|
|
void VisitVarTemplateDecl(VarTemplateDecl *D);
|
2010-06-22 17:55:07 +08:00
|
|
|
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
|
2011-05-06 05:57:07 +08:00
|
|
|
void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
|
2010-06-20 22:40:59 +08:00
|
|
|
void VisitUsingDecl(UsingDecl *D);
|
|
|
|
void VisitUsingShadowDecl(UsingShadowDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
|
2011-12-03 07:23:56 +08:00
|
|
|
void VisitImportDecl(ImportDecl *D);
|
2010-06-05 13:09:32 +08:00
|
|
|
void VisitAccessSpecDecl(AccessSpecDecl *D);
|
2010-06-30 06:47:00 +08:00
|
|
|
void VisitFriendDecl(FriendDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
void VisitFriendTemplateDecl(FriendTemplateDecl *D);
|
|
|
|
void VisitStaticAssertDecl(StaticAssertDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitBlockDecl(BlockDecl *BD);
|
2013-04-17 03:37:38 +08:00
|
|
|
void VisitCapturedDecl(CapturedDecl *CD);
|
2013-02-23 01:15:32 +08:00
|
|
|
void VisitEmptyDecl(EmptyDecl *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
|
2009-04-27 13:27:42 +08:00
|
|
|
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-01-04 01:27:13 +08:00
|
|
|
template<typename T>
|
2011-12-22 09:48:48 +08:00
|
|
|
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
|
2010-05-08 05:43:38 +08:00
|
|
|
|
2012-01-04 01:27:13 +08:00
|
|
|
template<typename T>
|
|
|
|
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
|
2013-09-10 00:55:27 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
|
|
|
|
RedeclarableResult &Redecl);
|
|
|
|
|
2010-05-30 15:21:58 +08:00
|
|
|
// FIXME: Reorder according to DeclNodes.td?
|
2009-04-27 13:27:42 +08:00
|
|
|
void VisitObjCMethodDecl(ObjCMethodDecl *D);
|
|
|
|
void VisitObjCContainerDecl(ObjCContainerDecl *D);
|
|
|
|
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
|
|
|
|
void VisitObjCIvarDecl(ObjCIvarDecl *D);
|
|
|
|
void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
|
|
|
|
void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
|
|
|
|
void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
|
|
|
|
void VisitObjCImplDecl(ObjCImplDecl *D);
|
|
|
|
void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
|
|
|
|
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
|
|
|
|
void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
|
|
|
|
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
|
|
|
|
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
|
2013-03-22 14:34:35 +08:00
|
|
|
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
uint64_t ASTDeclReader::GetCurrentCursorOffset() {
|
Introduce a global bit-offset continuous range map into the ASTReader,
so that we have one, simple way to map from global bit offsets to
local bit offsets. Eliminates a number of loops over the chain, and
generalizes for more interesting bit remappings.
Also, as an amusing oddity, we were computing global bit offsets
*backwards* for preprocessed entities (e.g., the directly included PCH
file in the chain would start at offset zero, rather than the original
PCH that occurs first in translation unit). Even more amusingly, it
made precompiled preambles work, because we were forgetting to adjust
the local bit offset to a global bit offset when storing preprocessed
entity offsets in the ASTUnit. Two wrongs made a right, and now
they're both right.
llvm-svn: 135750
2011-07-22 14:10:01 +08:00
|
|
|
return F.DeclsCursor.GetCurrentBitNo() + F.GlobalBitOffset;
|
2010-07-23 06:43:28 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::Visit(Decl *D) {
|
|
|
|
DeclVisitor<ASTDeclReader, void>::Visit(D);
|
2010-07-02 19:55:01 +08:00
|
|
|
|
2011-06-04 07:11:16 +08:00
|
|
|
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
|
|
|
|
if (DD->DeclInfo) {
|
|
|
|
DeclaratorDecl::ExtInfo *Info =
|
|
|
|
DD->DeclInfo.get<DeclaratorDecl::ExtInfo *>();
|
|
|
|
Info->TInfo =
|
|
|
|
GetTypeSourceInfo(Record, Idx);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DD->DeclInfo = GetTypeSourceInfo(Record, Idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-02 23:58:43 +08:00
|
|
|
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
|
2010-08-11 20:19:30 +08:00
|
|
|
// if we have a fully initialized TypeDecl, we can safely read its type now.
|
2010-12-11 01:03:06 +08:00
|
|
|
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
|
2011-12-16 11:12:41 +08:00
|
|
|
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
|
|
|
// if we have a fully initialized TypeDecl, we can safely read its type now.
|
|
|
|
ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull();
|
2010-07-02 23:58:43 +08:00
|
|
|
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
// FunctionDecl's body was written last after all other Stmts/Exprs.
|
2012-10-04 02:34:48 +08:00
|
|
|
// We only read it if FD doesn't already have a body (e.g., from another
|
|
|
|
// module).
|
2012-10-04 02:36:10 +08:00
|
|
|
// FIXME: Also consider = default and = delete.
|
|
|
|
// FIXME: Can we diagnose ODR violations somehow?
|
2012-10-10 01:21:28 +08:00
|
|
|
if (Record[Idx++]) {
|
|
|
|
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
|
|
|
|
HasPendingBody = true;
|
|
|
|
}
|
2010-07-02 23:58:43 +08:00
|
|
|
}
|
2010-07-02 19:55:01 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitDecl(Decl *D) {
|
2011-03-05 09:35:54 +08:00
|
|
|
if (D->isTemplateParameter()) {
|
|
|
|
// We don't want to deserialize the DeclContext of a template
|
|
|
|
// parameter immediately, because the template parameter might be
|
|
|
|
// used in the formulation of its DeclContext. Use the translation
|
|
|
|
// unit DeclContext as a placeholder.
|
2013-02-16 08:48:59 +08:00
|
|
|
GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
|
|
|
|
GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
|
|
|
|
Reader.addPendingDeclContextInfo(D,
|
|
|
|
SemaDCIDForTemplateParmDecl,
|
|
|
|
LexicalDCIDForTemplateParmDecl);
|
2011-09-10 05:34:22 +08:00
|
|
|
D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
|
2011-03-05 09:35:54 +08:00
|
|
|
} else {
|
2012-02-09 10:44:08 +08:00
|
|
|
DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx);
|
|
|
|
DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx);
|
2013-09-10 00:55:27 +08:00
|
|
|
DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
|
2012-02-09 15:46:54 +08:00
|
|
|
// Avoid calling setLexicalDeclContext() directly because it uses
|
|
|
|
// Decl::getASTContext() internally which is unsafe during derialization.
|
2013-09-10 00:55:27 +08:00
|
|
|
D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC,
|
|
|
|
Reader.getContext());
|
2011-03-05 09:35:54 +08:00
|
|
|
}
|
2011-10-28 02:47:35 +08:00
|
|
|
D->setLocation(Reader.ReadSourceLocation(F, RawLocation));
|
2009-04-27 13:27:42 +08:00
|
|
|
D->setInvalidDecl(Record[Idx++]);
|
2010-10-19 03:20:11 +08:00
|
|
|
if (Record[Idx++]) { // hasAttrs
|
2010-08-19 07:23:40 +08:00
|
|
|
AttrVec Attrs;
|
2010-10-19 03:20:11 +08:00
|
|
|
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
2012-02-09 15:46:54 +08:00
|
|
|
// Avoid calling setAttrs() directly because it uses Decl::getASTContext()
|
|
|
|
// internally which is unsafe during derialization.
|
2012-02-09 10:44:08 +08:00
|
|
|
D->setAttrsImpl(Attrs, Reader.getContext());
|
2010-08-19 07:23:40 +08:00
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
D->setImplicit(Record[Idx++]);
|
2013-09-05 08:02:25 +08:00
|
|
|
D->setIsUsed(Record[Idx++]);
|
2011-04-20 03:51:10 +08:00
|
|
|
D->setReferenced(Record[Idx++]);
|
2012-01-07 00:59:53 +08:00
|
|
|
D->setTopLevelDeclInObjCContainer(Record[Idx++]);
|
2009-04-27 13:27:42 +08:00
|
|
|
D->setAccess((AccessSpecifier)Record[Idx++]);
|
2011-09-10 08:09:20 +08:00
|
|
|
D->FromASTFile = true;
|
2012-01-07 00:59:53 +08:00
|
|
|
D->setModulePrivate(Record[Idx++]);
|
|
|
|
D->Hidden = D->isModulePrivate();
|
2012-01-07 00:22:39 +08:00
|
|
|
|
2011-12-02 06:20:10 +08:00
|
|
|
// Determine whether this declaration is part of a (sub)module. If so, it
|
|
|
|
// may not yet be visible.
|
|
|
|
if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
|
2012-01-10 01:30:44 +08:00
|
|
|
// Store the owning submodule ID in the declaration.
|
|
|
|
D->setOwningModuleID(SubmoduleID);
|
|
|
|
|
2011-12-02 06:20:10 +08:00
|
|
|
// Module-private declarations are never visible, so there is no work to do.
|
2012-01-07 00:59:53 +08:00
|
|
|
if (!D->isModulePrivate()) {
|
2011-12-02 06:20:10 +08:00
|
|
|
if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
|
|
|
|
if (Owner->NameVisibility != Module::AllVisible) {
|
2012-01-07 00:22:39 +08:00
|
|
|
// The owning module is not visible. Mark this declaration as hidden.
|
|
|
|
D->Hidden = true;
|
2011-12-02 06:20:10 +08:00
|
|
|
|
|
|
|
// Note that this declaration was hidden because its owning module is
|
|
|
|
// not yet visible.
|
|
|
|
Reader.HiddenNamesMap[Owner].push_back(D);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
|
2011-08-12 08:15:20 +08:00
|
|
|
llvm_unreachable("Translation units are not serialized");
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitDecl(ND);
|
2011-07-22 08:38:23 +08:00
|
|
|
ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitNamedDecl(TD);
|
2011-03-06 23:48:19 +08:00
|
|
|
TD->setLocStart(ReadSourceLocation(Record, Idx));
|
2010-07-02 19:55:01 +08:00
|
|
|
// Delay type reading until after we have fully initialized the decl.
|
2011-07-22 08:38:23 +08:00
|
|
|
TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2011-12-19 22:40:25 +08:00
|
|
|
void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
|
2012-01-05 00:44:10 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(TD);
|
2010-07-02 19:55:01 +08:00
|
|
|
VisitTypeDecl(TD);
|
2013-06-20 20:46:19 +08:00
|
|
|
TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx);
|
|
|
|
if (Record[Idx++]) { // isModed
|
|
|
|
QualType modedT = Reader.readType(F, Record, Idx);
|
|
|
|
TD->setModedTypeSourceInfo(TInfo, modedT);
|
|
|
|
} else
|
|
|
|
TD->setTypeSourceInfo(TInfo);
|
2012-01-05 00:44:10 +08:00
|
|
|
mergeRedeclarable(TD, Redecl);
|
2011-12-19 22:40:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
|
|
|
|
VisitTypedefNameDecl(TD);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2011-04-15 22:24:37 +08:00
|
|
|
void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
|
2011-12-19 22:40:25 +08:00
|
|
|
VisitTypedefNameDecl(TD);
|
2011-04-15 22:24:37 +08:00
|
|
|
}
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
|
2012-01-04 06:46:00 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(TD);
|
2011-10-27 01:53:41 +08:00
|
|
|
VisitTypeDecl(TD);
|
2012-01-04 06:46:00 +08:00
|
|
|
|
2010-09-09 03:31:22 +08:00
|
|
|
TD->IdentifierNamespace = Record[Idx++];
|
2009-04-27 13:27:42 +08:00
|
|
|
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
|
2011-10-07 14:10:15 +08:00
|
|
|
TD->setCompleteDefinition(Record[Idx++]);
|
2010-02-13 01:40:34 +08:00
|
|
|
TD->setEmbeddedInDeclarator(Record[Idx++]);
|
2011-10-01 06:11:31 +08:00
|
|
|
TD->setFreeStanding(Record[Idx++]);
|
2013-07-14 09:07:41 +08:00
|
|
|
TD->setCompleteDefinitionRequired(Record[Idx++]);
|
2010-10-05 23:59:54 +08:00
|
|
|
TD->setRBraceLoc(ReadSourceLocation(Record, Idx));
|
2012-01-04 06:46:00 +08:00
|
|
|
|
2010-10-16 02:21:24 +08:00
|
|
|
if (Record[Idx++]) { // hasExtInfo
|
2011-09-10 05:34:22 +08:00
|
|
|
TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
|
2010-10-16 02:21:24 +08:00
|
|
|
ReadQualifierInfo(*Info, Record, Idx);
|
2013-09-18 07:57:10 +08:00
|
|
|
TD->NamedDeclOrQualifier = Info;
|
2010-10-16 02:21:24 +08:00
|
|
|
} else
|
2013-09-18 07:57:10 +08:00
|
|
|
TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx);
|
2012-01-04 06:46:00 +08:00
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
mergeRedeclarable(TD, Redecl);
|
|
|
|
return Redecl;
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitTagDecl(ED);
|
2010-10-09 07:50:27 +08:00
|
|
|
if (TypeSourceInfo *TI = Reader.GetTypeSourceInfo(F, Record, Idx))
|
|
|
|
ED->setIntegerTypeSourceInfo(TI);
|
|
|
|
else
|
2011-07-22 08:38:23 +08:00
|
|
|
ED->setIntegerType(Reader.readType(F, Record, Idx));
|
|
|
|
ED->setPromotionType(Reader.readType(F, Record, Idx));
|
2010-05-06 16:49:23 +08:00
|
|
|
ED->setNumPositiveBits(Record[Idx++]);
|
|
|
|
ED->setNumNegativeBits(Record[Idx++]);
|
2010-10-09 07:50:27 +08:00
|
|
|
ED->IsScoped = Record[Idx++];
|
2010-12-04 02:54:17 +08:00
|
|
|
ED->IsScopedUsingClassTag = Record[Idx++];
|
2010-10-09 07:50:27 +08:00
|
|
|
ED->IsFixed = Record[Idx++];
|
2012-03-15 07:13:10 +08:00
|
|
|
|
|
|
|
if (EnumDecl *InstED = ReadDeclAs<EnumDecl>(Record, Idx)) {
|
|
|
|
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
|
|
|
|
SourceLocation POI = ReadSourceLocation(Record, Idx);
|
|
|
|
ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK);
|
|
|
|
ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
|
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
|
|
|
|
RedeclarableResult Redecl = VisitTagDecl(RD);
|
2009-04-27 13:27:42 +08:00
|
|
|
RD->setHasFlexibleArrayMember(Record[Idx++]);
|
|
|
|
RD->setAnonymousStructOrUnion(Record[Idx++]);
|
2009-07-09 00:37:44 +08:00
|
|
|
RD->setHasObjectMember(Record[Idx++]);
|
2013-01-26 07:57:05 +08:00
|
|
|
RD->setHasVolatileMember(Record[Idx++]);
|
2013-05-23 09:49:11 +08:00
|
|
|
return Redecl;
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitNamedDecl(VD);
|
2011-07-22 08:38:23 +08:00
|
|
|
VD->setType(Reader.readType(F, Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitValueDecl(ECD);
|
|
|
|
if (Record[Idx++])
|
2010-10-05 23:59:54 +08:00
|
|
|
ECD->setInitExpr(Reader.ReadExpr(F));
|
2009-04-27 13:27:42 +08:00
|
|
|
ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
2009-08-19 09:28:35 +08:00
|
|
|
VisitValueDecl(DD);
|
2011-03-08 16:55:46 +08:00
|
|
|
DD->setInnerLocStart(ReadSourceLocation(Record, Idx));
|
2010-10-16 02:21:24 +08:00
|
|
|
if (Record[Idx++]) { // hasExtInfo
|
|
|
|
DeclaratorDecl::ExtInfo *Info
|
2011-09-10 05:34:22 +08:00
|
|
|
= new (Reader.getContext()) DeclaratorDecl::ExtInfo();
|
2010-10-16 02:21:24 +08:00
|
|
|
ReadQualifierInfo(*Info, Record, Idx);
|
|
|
|
DD->DeclInfo = Info;
|
2011-06-04 07:11:16 +08:00
|
|
|
}
|
2009-08-19 09:28:35 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(FD);
|
2011-10-27 01:53:41 +08:00
|
|
|
VisitDeclaratorDecl(FD);
|
2010-05-08 05:43:38 +08:00
|
|
|
|
2010-10-16 02:21:24 +08:00
|
|
|
ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx);
|
2010-07-05 18:38:01 +08:00
|
|
|
FD->IdentifierNamespace = Record[Idx++];
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
|
|
|
|
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
|
|
|
|
// after everything else is read.
|
2013-04-04 03:27:57 +08:00
|
|
|
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
FD->SClass = (StorageClass)Record[Idx++];
|
|
|
|
FD->IsInline = Record[Idx++];
|
|
|
|
FD->IsInlineSpecified = Record[Idx++];
|
|
|
|
FD->IsVirtualAsWritten = Record[Idx++];
|
|
|
|
FD->IsPure = Record[Idx++];
|
|
|
|
FD->HasInheritedPrototype = Record[Idx++];
|
|
|
|
FD->HasWrittenPrototype = Record[Idx++];
|
|
|
|
FD->IsDeleted = Record[Idx++];
|
|
|
|
FD->IsTrivial = Record[Idx++];
|
|
|
|
FD->IsDefaulted = Record[Idx++];
|
|
|
|
FD->IsExplicitlyDefaulted = Record[Idx++];
|
|
|
|
FD->HasImplicitReturnZero = Record[Idx++];
|
|
|
|
FD->IsConstexpr = Record[Idx++];
|
2012-12-07 02:59:10 +08:00
|
|
|
FD->HasSkippedBody = Record[Idx++];
|
2013-08-08 05:41:30 +08:00
|
|
|
FD->IsLateTemplateParsed = Record[Idx++];
|
2013-05-26 01:16:20 +08:00
|
|
|
FD->setCachedLinkage(Linkage(Record[Idx++]));
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
2010-06-22 17:55:07 +08:00
|
|
|
switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
|
|
|
|
case FunctionDecl::TK_NonTemplate:
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
mergeRedeclarable(FD, Redecl);
|
2010-06-22 17:55:07 +08:00
|
|
|
break;
|
|
|
|
case FunctionDecl::TK_FunctionTemplate:
|
2011-07-22 06:35:25 +08:00
|
|
|
FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record,
|
|
|
|
Idx));
|
2010-06-22 17:55:07 +08:00
|
|
|
break;
|
|
|
|
case FunctionDecl::TK_MemberSpecialization: {
|
2011-07-22 06:35:25 +08:00
|
|
|
FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>(Record, Idx);
|
2010-06-22 17:55:07 +08:00
|
|
|
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
|
2010-10-05 23:59:54 +08:00
|
|
|
SourceLocation POI = ReadSourceLocation(Record, Idx);
|
2011-09-10 05:34:22 +08:00
|
|
|
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
|
2010-06-22 17:55:07 +08:00
|
|
|
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FunctionDecl::TK_FunctionTemplateSpecialization: {
|
2011-07-22 06:35:25 +08:00
|
|
|
FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>(Record,
|
|
|
|
Idx);
|
2010-06-22 17:55:07 +08:00
|
|
|
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
|
|
|
|
|
|
|
|
// Template arguments.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
2010-10-05 23:59:54 +08:00
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
2010-06-22 17:55:07 +08:00
|
|
|
|
|
|
|
// Template args as written.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
|
2010-06-22 17:55:07 +08:00
|
|
|
SourceLocation LAngleLoc, RAngleLoc;
|
2011-09-23 04:07:09 +08:00
|
|
|
bool HasTemplateArgumentsAsWritten = Record[Idx++];
|
|
|
|
if (HasTemplateArgumentsAsWritten) {
|
2010-07-02 19:55:40 +08:00
|
|
|
unsigned NumTemplateArgLocs = Record[Idx++];
|
|
|
|
TemplArgLocs.reserve(NumTemplateArgLocs);
|
|
|
|
for (unsigned i=0; i != NumTemplateArgLocs; ++i)
|
2010-07-23 06:43:28 +08:00
|
|
|
TemplArgLocs.push_back(
|
2010-10-05 23:59:54 +08:00
|
|
|
Reader.ReadTemplateArgumentLoc(F, Record, Idx));
|
2010-07-02 19:55:40 +08:00
|
|
|
|
2010-10-05 23:59:54 +08:00
|
|
|
LAngleLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
RAngleLoc = ReadSourceLocation(Record, Idx);
|
2010-06-22 17:55:07 +08:00
|
|
|
}
|
2010-07-05 18:37:55 +08:00
|
|
|
|
2010-10-05 23:59:54 +08:00
|
|
|
SourceLocation POI = ReadSourceLocation(Record, Idx);
|
2010-06-22 17:55:07 +08:00
|
|
|
|
2011-09-10 05:34:22 +08:00
|
|
|
ASTContext &C = Reader.getContext();
|
2010-09-09 19:28:23 +08:00
|
|
|
TemplateArgumentList *TemplArgList
|
2010-11-08 07:05:16 +08:00
|
|
|
= TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
|
2011-09-23 04:07:09 +08:00
|
|
|
TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
|
2010-09-09 19:28:23 +08:00
|
|
|
for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i)
|
2011-09-23 04:07:09 +08:00
|
|
|
TemplArgsInfo.addArgument(TemplArgLocs[i]);
|
2010-09-09 19:28:23 +08:00
|
|
|
FunctionTemplateSpecializationInfo *FTInfo
|
|
|
|
= FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK,
|
|
|
|
TemplArgList,
|
2011-09-23 04:07:09 +08:00
|
|
|
HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0,
|
|
|
|
POI);
|
2010-09-09 19:28:23 +08:00
|
|
|
FD->TemplateOrSpecialization = FTInfo;
|
2010-09-09 03:31:22 +08:00
|
|
|
|
2010-09-09 19:28:23 +08:00
|
|
|
if (FD->isCanonicalDecl()) { // if canonical add to template's set.
|
2010-09-13 19:45:48 +08:00
|
|
|
// The template that contains the specializations set. It's not safe to
|
|
|
|
// use getCanonicalDecl on Template since it may still be initializing.
|
|
|
|
FunctionTemplateDecl *CanonTemplate
|
2011-07-22 06:35:25 +08:00
|
|
|
= ReadDeclAs<FunctionTemplateDecl>(Record, Idx);
|
2010-09-09 19:28:23 +08:00
|
|
|
// Get the InsertPos by FindNodeOrInsertPos() instead of calling
|
|
|
|
// InsertNode(FTInfo) directly to avoid the getASTContext() call in
|
|
|
|
// FunctionTemplateSpecializationInfo's Profile().
|
|
|
|
// We avoid getASTContext because a decl in the parent hierarchy may
|
|
|
|
// be initializing.
|
2010-09-09 03:31:22 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(),
|
|
|
|
TemplArgs.size(), C);
|
|
|
|
void *InsertPos = 0;
|
2013-06-28 12:37:53 +08:00
|
|
|
FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
|
|
|
|
CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
|
2012-09-11 07:28:22 +08:00
|
|
|
if (InsertPos)
|
2013-06-28 12:37:53 +08:00
|
|
|
CommonPtr->Specializations.InsertNode(FTInfo, InsertPos);
|
|
|
|
else {
|
|
|
|
assert(Reader.getContext().getLangOpts().Modules &&
|
|
|
|
"already deserialized this template specialization");
|
|
|
|
// FIXME: This specialization is a redeclaration of one from another
|
|
|
|
// module. Merge it.
|
|
|
|
}
|
2010-09-09 03:31:22 +08:00
|
|
|
}
|
2010-06-28 17:31:34 +08:00
|
|
|
break;
|
2010-06-22 17:55:07 +08:00
|
|
|
}
|
|
|
|
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
|
|
|
|
// Templates.
|
|
|
|
UnresolvedSet<8> TemplDecls;
|
|
|
|
unsigned NumTemplates = Record[Idx++];
|
|
|
|
while (NumTemplates--)
|
2011-07-22 06:35:25 +08:00
|
|
|
TemplDecls.addDecl(ReadDeclAs<NamedDecl>(Record, Idx));
|
2010-06-22 17:55:07 +08:00
|
|
|
|
|
|
|
// Templates args.
|
|
|
|
TemplateArgumentListInfo TemplArgs;
|
|
|
|
unsigned NumArgs = Record[Idx++];
|
|
|
|
while (NumArgs--)
|
2010-10-05 23:59:54 +08:00
|
|
|
TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(F, Record, Idx));
|
|
|
|
TemplArgs.setLAngleLoc(ReadSourceLocation(Record, Idx));
|
|
|
|
TemplArgs.setRAngleLoc(ReadSourceLocation(Record, Idx));
|
2010-06-22 17:55:07 +08:00
|
|
|
|
2011-09-10 05:34:22 +08:00
|
|
|
FD->setDependentTemplateSpecialization(Reader.getContext(),
|
2010-06-22 17:55:07 +08:00
|
|
|
TemplDecls, TemplArgs);
|
2010-06-28 17:31:34 +08:00
|
|
|
break;
|
2010-06-22 17:55:07 +08:00
|
|
|
}
|
|
|
|
}
|
2010-07-02 19:55:40 +08:00
|
|
|
|
2010-05-08 05:43:38 +08:00
|
|
|
// Read in the parameters.
|
2009-04-27 13:27:42 +08:00
|
|
|
unsigned NumParams = Record[Idx++];
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ParmVarDecl *, 16> Params;
|
2009-04-27 13:27:42 +08:00
|
|
|
Params.reserve(NumParams);
|
|
|
|
for (unsigned I = 0; I != NumParams; ++I)
|
2011-07-22 06:35:25 +08:00
|
|
|
Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
|
2011-09-22 02:16:56 +08:00
|
|
|
FD->setParams(Reader.getContext(), Params);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitNamedDecl(MD);
|
|
|
|
if (Record[Idx++]) {
|
2012-10-10 01:21:28 +08:00
|
|
|
// Load the body on-demand. Most clients won't care, because method
|
|
|
|
// definitions rarely show up in headers.
|
|
|
|
Reader.PendingBodies[MD] = GetCurrentCursorOffset();
|
|
|
|
HasPendingBody = true;
|
2011-07-22 06:35:25 +08:00
|
|
|
MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx));
|
|
|
|
MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
MD->setInstanceMethod(Record[Idx++]);
|
|
|
|
MD->setVariadic(Record[Idx++]);
|
2012-10-11 00:42:25 +08:00
|
|
|
MD->setPropertyAccessor(Record[Idx++]);
|
2010-07-23 02:24:20 +08:00
|
|
|
MD->setDefined(Record[Idx++]);
|
2012-05-10 00:12:57 +08:00
|
|
|
MD->IsOverriding = Record[Idx++];
|
2012-12-07 02:59:10 +08:00
|
|
|
MD->HasSkippedBody = Record[Idx++];
|
2011-10-15 01:41:52 +08:00
|
|
|
|
|
|
|
MD->IsRedeclaration = Record[Idx++];
|
|
|
|
MD->HasRedeclaration = Record[Idx++];
|
|
|
|
if (MD->HasRedeclaration)
|
|
|
|
Reader.getContext().setObjCMethodRedeclaration(MD,
|
|
|
|
ReadDeclAs<ObjCMethodDecl>(Record, Idx));
|
|
|
|
|
2009-04-27 13:27:42 +08:00
|
|
|
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
|
|
|
|
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
|
2011-06-11 09:09:30 +08:00
|
|
|
MD->SetRelatedResultType(Record[Idx++]);
|
2011-07-22 08:38:23 +08:00
|
|
|
MD->setResultType(Reader.readType(F, Record, Idx));
|
2010-10-05 23:59:54 +08:00
|
|
|
MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
|
2012-06-16 08:46:02 +08:00
|
|
|
MD->DeclEndLoc = ReadSourceLocation(Record, Idx);
|
2009-04-27 13:27:42 +08:00
|
|
|
unsigned NumParams = Record[Idx++];
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ParmVarDecl *, 16> Params;
|
2009-04-27 13:27:42 +08:00
|
|
|
Params.reserve(NumParams);
|
|
|
|
for (unsigned I = 0; I != NumParams; ++I)
|
2011-07-22 06:35:25 +08:00
|
|
|
Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
|
2011-10-03 14:37:04 +08:00
|
|
|
|
|
|
|
MD->SelLocsKind = Record[Idx++];
|
|
|
|
unsigned NumStoredSelLocs = Record[Idx++];
|
|
|
|
SmallVector<SourceLocation, 16> SelLocs;
|
|
|
|
SelLocs.reserve(NumStoredSelLocs);
|
|
|
|
for (unsigned i = 0; i != NumStoredSelLocs; ++i)
|
|
|
|
SelLocs.push_back(ReadSourceLocation(Record, Idx));
|
|
|
|
|
|
|
|
MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitNamedDecl(CD);
|
2011-10-04 12:48:02 +08:00
|
|
|
CD->setAtStartLoc(ReadSourceLocation(Record, Idx));
|
|
|
|
CD->setAtEndRange(ReadSourceRange(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
2011-12-22 09:48:48 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitObjCContainerDecl(ID);
|
2011-12-16 11:12:41 +08:00
|
|
|
TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
|
2012-01-04 01:27:13 +08:00
|
|
|
mergeRedeclarable(ID, Redecl);
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-01-16 02:17:48 +08:00
|
|
|
if (Record[Idx++]) {
|
2011-12-15 13:27:12 +08:00
|
|
|
// Read the definition.
|
|
|
|
ID->allocateDefinitionData();
|
|
|
|
|
2012-01-16 02:08:05 +08:00
|
|
|
// Set the definition data of the canonical declaration, so other
|
|
|
|
// redeclarations will see it.
|
|
|
|
ID->getCanonicalDecl()->Data = ID->Data;
|
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
ObjCInterfaceDecl::DefinitionData &Data = ID->data();
|
|
|
|
|
|
|
|
// Read the superclass.
|
|
|
|
Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
|
|
|
|
Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
2011-12-16 06:34:59 +08:00
|
|
|
Data.EndLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
// Read the directly referenced protocols and their SourceLocations.
|
|
|
|
unsigned NumProtocols = Record[Idx++];
|
|
|
|
SmallVector<ObjCProtocolDecl *, 16> Protocols;
|
|
|
|
Protocols.reserve(NumProtocols);
|
|
|
|
for (unsigned I = 0; I != NumProtocols; ++I)
|
|
|
|
Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
|
|
|
|
SmallVector<SourceLocation, 16> ProtoLocs;
|
|
|
|
ProtoLocs.reserve(NumProtocols);
|
|
|
|
for (unsigned I = 0; I != NumProtocols; ++I)
|
|
|
|
ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
|
|
|
|
ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
|
|
|
|
Reader.getContext());
|
2010-09-01 09:21:15 +08:00
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
// Read the transitive closure of protocols referenced by this class.
|
|
|
|
NumProtocols = Record[Idx++];
|
|
|
|
Protocols.clear();
|
|
|
|
Protocols.reserve(NumProtocols);
|
|
|
|
for (unsigned I = 0; I != NumProtocols; ++I)
|
|
|
|
Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
|
|
|
|
ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols,
|
|
|
|
Reader.getContext());
|
2010-09-01 09:21:15 +08:00
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
// We will rebuild this list lazily.
|
|
|
|
ID->setIvarList(0);
|
|
|
|
|
2011-12-20 04:51:16 +08:00
|
|
|
// Note that we have deserialized a definition.
|
|
|
|
Reader.PendingDefinitions.insert(ID);
|
2012-01-27 09:47:08 +08:00
|
|
|
|
|
|
|
// Note that we've loaded this Objective-C class.
|
|
|
|
Reader.ObjCClassesLoaded.push_back(ID);
|
2012-01-16 02:08:05 +08:00
|
|
|
} else {
|
|
|
|
ID->Data = ID->getCanonicalDecl()->Data;
|
2011-12-15 13:27:12 +08:00
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitFieldDecl(IVD);
|
|
|
|
IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
|
2010-08-21 05:21:08 +08:00
|
|
|
// This field will be built lazily.
|
|
|
|
IVD->setNextIvar(0);
|
2010-07-18 02:35:47 +08:00
|
|
|
bool synth = Record[Idx++];
|
|
|
|
IVD->setSynthesize(synth);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
|
2012-01-02 05:47:52 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(PD);
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitObjCContainerDecl(PD);
|
2012-01-04 01:27:13 +08:00
|
|
|
mergeRedeclarable(PD, Redecl);
|
2012-01-02 05:47:52 +08:00
|
|
|
|
2012-01-16 02:17:48 +08:00
|
|
|
if (Record[Idx++]) {
|
2012-01-02 03:29:29 +08:00
|
|
|
// Read the definition.
|
|
|
|
PD->allocateDefinitionData();
|
|
|
|
|
2012-01-16 02:08:05 +08:00
|
|
|
// Set the definition data of the canonical declaration, so other
|
|
|
|
// redeclarations will see it.
|
|
|
|
PD->getCanonicalDecl()->Data = PD->Data;
|
|
|
|
|
2012-01-02 03:29:29 +08:00
|
|
|
unsigned NumProtoRefs = Record[Idx++];
|
|
|
|
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
|
|
|
|
ProtoRefs.reserve(NumProtoRefs);
|
|
|
|
for (unsigned I = 0; I != NumProtoRefs; ++I)
|
|
|
|
ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
|
|
|
|
SmallVector<SourceLocation, 16> ProtoLocs;
|
|
|
|
ProtoLocs.reserve(NumProtoRefs);
|
|
|
|
for (unsigned I = 0; I != NumProtoRefs; ++I)
|
|
|
|
ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
|
|
|
|
PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
|
|
|
|
Reader.getContext());
|
|
|
|
|
2012-01-02 03:51:50 +08:00
|
|
|
// Note that we have deserialized a definition.
|
|
|
|
Reader.PendingDefinitions.insert(PD);
|
2012-01-16 02:08:05 +08:00
|
|
|
} else {
|
|
|
|
PD->Data = PD->getCanonicalDecl()->Data;
|
2012-01-02 03:29:29 +08:00
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitFieldDecl(FD);
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitObjCContainerDecl(CD);
|
2012-01-27 09:47:08 +08:00
|
|
|
CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx));
|
2012-02-21 04:09:20 +08:00
|
|
|
CD->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
|
|
|
|
CD->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
|
2012-01-27 09:47:08 +08:00
|
|
|
|
|
|
|
// Note that this category has been deserialized. We do this before
|
|
|
|
// deserializing the interface declaration, so that it will consider this
|
|
|
|
/// category.
|
|
|
|
Reader.CategoriesDeserialized.insert(CD);
|
|
|
|
|
2011-08-31 03:43:26 +08:00
|
|
|
CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
|
2009-04-27 13:27:42 +08:00
|
|
|
unsigned NumProtoRefs = Record[Idx++];
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
|
2009-04-27 13:27:42 +08:00
|
|
|
ProtoRefs.reserve(NumProtoRefs);
|
|
|
|
for (unsigned I = 0; I != NumProtoRefs; ++I)
|
2011-07-22 06:35:25 +08:00
|
|
|
ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<SourceLocation, 16> ProtoLocs;
|
2010-01-16 23:02:53 +08:00
|
|
|
ProtoLocs.reserve(NumProtoRefs);
|
|
|
|
for (unsigned I = 0; I != NumProtoRefs; ++I)
|
2010-10-05 23:59:54 +08:00
|
|
|
ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
|
2010-01-16 23:02:53 +08:00
|
|
|
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
|
2011-09-10 05:34:22 +08:00
|
|
|
Reader.getContext());
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitNamedDecl(CAD);
|
2011-07-22 06:35:25 +08:00
|
|
|
CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitNamedDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->setAtLoc(ReadSourceLocation(Record, Idx));
|
2012-03-01 06:18:55 +08:00
|
|
|
D->setLParenLoc(ReadSourceLocation(Record, Idx));
|
2010-10-05 23:59:54 +08:00
|
|
|
D->setType(GetTypeSourceInfo(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
// FIXME: stable encoding
|
|
|
|
D->setPropertyAttributes(
|
|
|
|
(ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
|
2010-06-23 07:20:40 +08:00
|
|
|
D->setPropertyAttributesAsWritten(
|
|
|
|
(ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
|
2009-04-27 13:27:42 +08:00
|
|
|
// FIXME: stable encoding
|
|
|
|
D->setPropertyImplementation(
|
|
|
|
(ObjCPropertyDecl::PropertyControl)Record[Idx++]);
|
2011-07-22 08:38:23 +08:00
|
|
|
D->setGetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector());
|
|
|
|
D->setSetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector());
|
2011-07-22 06:35:25 +08:00
|
|
|
D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx));
|
|
|
|
D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx));
|
|
|
|
D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
|
2009-07-28 03:04:32 +08:00
|
|
|
VisitObjCContainerDecl(D);
|
2011-07-22 06:35:25 +08:00
|
|
|
D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitObjCImplDecl(D);
|
2011-07-29 04:55:49 +08:00
|
|
|
D->setIdentifier(Reader.GetIdentifierInfo(F, Record, Idx));
|
2011-12-09 08:31:40 +08:00
|
|
|
D->CategoryNameLoc = ReadSourceLocation(Record, Idx);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitObjCImplDecl(D);
|
2011-07-22 06:35:25 +08:00
|
|
|
D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
|
2013-05-04 02:05:44 +08:00
|
|
|
D->SuperLoc = ReadSourceLocation(Record, Idx);
|
2012-02-21 04:09:20 +08:00
|
|
|
D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
|
|
|
|
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
|
2012-10-17 12:53:31 +08:00
|
|
|
D->setHasNonZeroConstructors(Record[Idx++]);
|
|
|
|
D->setHasDestructors(Record[Idx++]);
|
2010-08-09 18:54:20 +08:00
|
|
|
llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
|
2011-01-09 04:30:50 +08:00
|
|
|
= Reader.ReadCXXCtorInitializers(F, Record, Idx);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->setAtLoc(ReadSourceLocation(Record, Idx));
|
2011-07-22 06:35:25 +08:00
|
|
|
D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>(Record, Idx));
|
|
|
|
D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>(Record, Idx);
|
2010-11-17 09:03:52 +08:00
|
|
|
D->IvarLoc = ReadSourceLocation(Record, Idx);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->setGetterCXXConstructor(Reader.ReadExpr(F));
|
|
|
|
D->setSetterCXXAssignment(Reader.ReadExpr(F));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
|
2009-08-19 09:28:35 +08:00
|
|
|
VisitDeclaratorDecl(FD);
|
2012-06-10 11:12:00 +08:00
|
|
|
FD->Mutable = Record[Idx++];
|
|
|
|
if (int BitWidthOrInitializer = Record[Idx++]) {
|
|
|
|
FD->InitializerOrBitWidth.setInt(BitWidthOrInitializer - 1);
|
|
|
|
FD->InitializerOrBitWidth.setPointer(Reader.ReadExpr(F));
|
|
|
|
}
|
2010-07-05 05:44:35 +08:00
|
|
|
if (!FD->getDeclName()) {
|
2011-07-22 06:35:25 +08:00
|
|
|
if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx))
|
2011-09-10 05:34:22 +08:00
|
|
|
Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
|
2010-07-05 05:44:35 +08:00
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2013-04-16 15:28:30 +08:00
|
|
|
void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
|
|
|
|
VisitDeclaratorDecl(PD);
|
|
|
|
PD->GetterId = Reader.GetIdentifierInfo(F, Record, Idx);
|
|
|
|
PD->SetterId = Reader.GetIdentifierInfo(F, Record, Idx);
|
|
|
|
}
|
|
|
|
|
2010-11-21 14:08:52 +08:00
|
|
|
void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
|
|
|
|
VisitValueDecl(FD);
|
|
|
|
|
|
|
|
FD->ChainingSize = Record[Idx++];
|
|
|
|
assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2");
|
2011-09-10 05:34:22 +08:00
|
|
|
FD->Chaining = new (Reader.getContext())NamedDecl*[FD->ChainingSize];
|
2010-11-21 14:08:52 +08:00
|
|
|
|
|
|
|
for (unsigned I = 0; I != FD->ChainingSize; ++I)
|
2011-07-22 06:35:25 +08:00
|
|
|
FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx);
|
2010-11-21 14:08:52 +08:00
|
|
|
}
|
|
|
|
|
2013-08-06 09:03:05 +08:00
|
|
|
ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
|
2012-01-05 01:21:36 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(VD);
|
2011-10-27 01:53:41 +08:00
|
|
|
VisitDeclaratorDecl(VD);
|
2013-04-04 03:27:57 +08:00
|
|
|
|
2011-05-01 10:13:58 +08:00
|
|
|
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
|
2013-05-04 16:27:07 +08:00
|
|
|
VD->VarDeclBits.TSCSpec = Record[Idx++];
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
VD->VarDeclBits.InitStyle = Record[Idx++];
|
2011-05-01 10:13:58 +08:00
|
|
|
VD->VarDeclBits.ExceptionVar = Record[Idx++];
|
|
|
|
VD->VarDeclBits.NRVOVariable = Record[Idx++];
|
|
|
|
VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
|
2011-06-17 14:42:21 +08:00
|
|
|
VD->VarDeclBits.ARCPseudoStrong = Record[Idx++];
|
2012-09-21 07:43:29 +08:00
|
|
|
VD->VarDeclBits.IsConstexpr = Record[Idx++];
|
2013-08-14 02:18:50 +08:00
|
|
|
VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
|
2013-09-20 09:15:31 +08:00
|
|
|
Linkage VarLinkage = Linkage(Record[Idx++]);
|
|
|
|
VD->setCachedLinkage(VarLinkage);
|
|
|
|
|
|
|
|
// Reconstruct the one piece of the IdentifierNamespace that we need.
|
|
|
|
if (VarLinkage != NoLinkage &&
|
|
|
|
VD->getLexicalDeclContext()->isFunctionOrMethod())
|
|
|
|
VD->setLocalExternDecl();
|
2013-05-26 01:16:20 +08:00
|
|
|
|
2012-01-14 07:49:34 +08:00
|
|
|
// Only true variables (not parameters or implicit parameters) can be merged.
|
2013-08-14 11:09:19 +08:00
|
|
|
if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam)
|
2012-01-14 07:49:34 +08:00
|
|
|
mergeRedeclarable(VD, Redecl);
|
2012-01-05 01:21:36 +08:00
|
|
|
|
2011-12-19 14:19:21 +08:00
|
|
|
if (uint64_t Val = Record[Idx++]) {
|
2010-10-05 23:59:54 +08:00
|
|
|
VD->setInit(Reader.ReadExpr(F));
|
2011-12-19 14:19:21 +08:00
|
|
|
if (Val > 1) {
|
|
|
|
EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
|
|
|
|
Eval->CheckedICE = true;
|
|
|
|
Eval->IsICE = Val == 3;
|
|
|
|
}
|
|
|
|
}
|
2010-07-05 05:44:00 +08:00
|
|
|
|
2013-08-14 11:09:19 +08:00
|
|
|
enum VarKind {
|
|
|
|
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
|
|
|
|
};
|
|
|
|
switch ((VarKind)Record[Idx++]) {
|
|
|
|
case VarNotTemplate:
|
|
|
|
break;
|
|
|
|
case VarTemplate:
|
|
|
|
VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx));
|
|
|
|
break;
|
|
|
|
case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
|
2011-07-22 06:35:25 +08:00
|
|
|
VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx);
|
2010-07-05 05:44:00 +08:00
|
|
|
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
|
2010-10-05 23:59:54 +08:00
|
|
|
SourceLocation POI = ReadSourceLocation(Record, Idx);
|
2011-09-10 05:34:22 +08:00
|
|
|
Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
|
2013-08-14 11:09:19 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-07-05 05:44:00 +08:00
|
|
|
}
|
2013-08-06 09:03:05 +08:00
|
|
|
|
|
|
|
return Redecl;
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitVarDecl(PD);
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitVarDecl(PD);
|
2011-05-02 08:30:12 +08:00
|
|
|
unsigned isObjCMethodParam = Record[Idx++];
|
|
|
|
unsigned scopeDepth = Record[Idx++];
|
|
|
|
unsigned scopeIndex = Record[Idx++];
|
|
|
|
unsigned declQualifier = Record[Idx++];
|
|
|
|
if (isObjCMethodParam) {
|
|
|
|
assert(scopeDepth == 0);
|
|
|
|
PD->setObjCMethodScopeInfo(scopeIndex);
|
|
|
|
PD->ParmVarDeclBits.ScopeDepthOrObjCQuals = declQualifier;
|
|
|
|
} else {
|
|
|
|
PD->setScopeInfo(scopeDepth, scopeIndex);
|
|
|
|
}
|
2011-05-01 10:13:58 +08:00
|
|
|
PD->ParmVarDeclBits.IsKNRPromoted = Record[Idx++];
|
|
|
|
PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++];
|
2010-07-05 05:44:07 +08:00
|
|
|
if (Record[Idx++]) // hasUninstantiatedDefaultArg.
|
2010-10-05 23:59:54 +08:00
|
|
|
PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F));
|
2013-06-25 06:51:00 +08:00
|
|
|
|
|
|
|
// FIXME: If this is a redeclaration of a function from another module, handle
|
|
|
|
// inheritance of default arguments.
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitDecl(AD);
|
2010-10-05 23:59:54 +08:00
|
|
|
AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(F)));
|
2011-03-03 22:20:18 +08:00
|
|
|
AD->setRParenLoc(ReadSourceLocation(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
|
2009-04-27 13:27:42 +08:00
|
|
|
VisitDecl(BD);
|
2010-10-05 23:59:54 +08:00
|
|
|
BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(F)));
|
|
|
|
BD->setSignatureAsWritten(GetTypeSourceInfo(Record, Idx));
|
2009-04-27 13:27:42 +08:00
|
|
|
unsigned NumParams = Record[Idx++];
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ParmVarDecl *, 16> Params;
|
2009-04-27 13:27:42 +08:00
|
|
|
Params.reserve(NumParams);
|
|
|
|
for (unsigned I = 0; I != NumParams; ++I)
|
2011-07-22 06:35:25 +08:00
|
|
|
Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
|
2011-09-22 02:16:56 +08:00
|
|
|
BD->setParams(Params);
|
2011-02-02 21:00:07 +08:00
|
|
|
|
2012-04-14 01:33:29 +08:00
|
|
|
BD->setIsVariadic(Record[Idx++]);
|
|
|
|
BD->setBlockMissingReturnType(Record[Idx++]);
|
|
|
|
BD->setIsConversionFromLambda(Record[Idx++]);
|
|
|
|
|
2011-02-02 21:00:07 +08:00
|
|
|
bool capturesCXXThis = Record[Idx++];
|
2011-02-07 18:33:21 +08:00
|
|
|
unsigned numCaptures = Record[Idx++];
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<BlockDecl::Capture, 16> captures;
|
2011-02-07 18:33:21 +08:00
|
|
|
captures.reserve(numCaptures);
|
|
|
|
for (unsigned i = 0; i != numCaptures; ++i) {
|
2011-07-22 06:35:25 +08:00
|
|
|
VarDecl *decl = ReadDeclAs<VarDecl>(Record, Idx);
|
2011-02-07 18:33:21 +08:00
|
|
|
unsigned flags = Record[Idx++];
|
|
|
|
bool byRef = (flags & 1);
|
|
|
|
bool nested = (flags & 2);
|
|
|
|
Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : 0);
|
|
|
|
|
|
|
|
captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
|
|
|
|
}
|
2011-09-10 05:34:22 +08:00
|
|
|
BD->setCaptures(Reader.getContext(), captures.begin(),
|
2011-02-07 18:33:21 +08:00
|
|
|
captures.end(), capturesCXXThis);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2013-05-04 03:20:19 +08:00
|
|
|
void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
|
|
|
|
VisitDecl(CD);
|
|
|
|
// Body is set by VisitCapturedStmt.
|
|
|
|
for (unsigned i = 0; i < CD->NumParams; ++i)
|
|
|
|
CD->setParam(i, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
|
2013-04-17 03:37:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitDecl(D);
|
|
|
|
D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]);
|
2011-03-09 00:41:52 +08:00
|
|
|
D->setExternLoc(ReadSourceLocation(Record, Idx));
|
2011-03-03 22:52:38 +08:00
|
|
|
D->setRBraceLoc(ReadSourceLocation(Record, Idx));
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2011-02-17 15:39:24 +08:00
|
|
|
void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
|
|
|
|
VisitNamedDecl(D);
|
2011-03-06 02:21:20 +08:00
|
|
|
D->setLocStart(ReadSourceLocation(Record, Idx));
|
2011-02-17 15:39:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
|
2012-01-07 17:11:48 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(D);
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitNamedDecl(D);
|
2012-01-07 17:11:48 +08:00
|
|
|
D->setInline(Record[Idx++]);
|
2011-03-08 20:38:20 +08:00
|
|
|
D->LocStart = ReadSourceLocation(Record, Idx);
|
|
|
|
D->RBraceLoc = ReadSourceLocation(Record, Idx);
|
2013-05-23 09:49:11 +08:00
|
|
|
// FIXME: At the point of this call, D->getCanonicalDecl() returns 0.
|
2012-01-10 01:30:44 +08:00
|
|
|
mergeRedeclarable(D, Redecl);
|
|
|
|
|
2012-01-07 17:11:48 +08:00
|
|
|
if (Redecl.getFirstID() == ThisDeclID) {
|
2012-01-10 02:07:24 +08:00
|
|
|
// Each module has its own anonymous namespace, which is disjoint from
|
|
|
|
// any other module's anonymous namespaces, so don't attach the anonymous
|
|
|
|
// namespace at all.
|
|
|
|
NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
|
|
|
|
if (F.Kind != MK_Module)
|
|
|
|
D->setAnonymousNamespace(Anon);
|
2012-01-07 17:11:48 +08:00
|
|
|
} else {
|
|
|
|
// Link this namespace back to the first declaration, which has already
|
|
|
|
// been deserialized.
|
|
|
|
D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration());
|
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitNamedDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
D->IdentLoc = ReadSourceLocation(Record, Idx);
|
2011-02-26 01:08:07 +08:00
|
|
|
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
|
2011-07-22 06:35:25 +08:00
|
|
|
D->Namespace = ReadDeclAs<NamedDecl>(Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitNamedDecl(D);
|
2013-07-22 18:54:09 +08:00
|
|
|
D->setUsingLoc(ReadSourceLocation(Record, Idx));
|
2011-02-25 08:36:19 +08:00
|
|
|
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
|
2010-10-16 02:21:24 +08:00
|
|
|
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
|
2012-01-08 03:09:05 +08:00
|
|
|
D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx));
|
2013-07-22 18:54:09 +08:00
|
|
|
D->setTypename(Record[Idx++]);
|
2011-07-22 06:35:25 +08:00
|
|
|
if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx))
|
2011-09-10 05:34:22 +08:00
|
|
|
Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitNamedDecl(D);
|
2011-07-22 06:35:25 +08:00
|
|
|
D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx));
|
|
|
|
D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx);
|
|
|
|
UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx);
|
2010-07-05 05:44:35 +08:00
|
|
|
if (Pattern)
|
2011-09-10 05:34:22 +08:00
|
|
|
Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitNamedDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->UsingLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
|
2011-02-26 00:33:46 +08:00
|
|
|
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
|
2011-07-22 06:35:25 +08:00
|
|
|
D->NominatedNamespace = ReadDeclAs<NamedDecl>(Record, Idx);
|
|
|
|
D->CommonAncestor = ReadDeclAs<DeclContext>(Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitValueDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->setUsingLoc(ReadSourceLocation(Record, Idx));
|
2011-02-25 08:36:19 +08:00
|
|
|
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
|
2010-10-16 02:21:24 +08:00
|
|
|
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
|
2010-05-08 05:43:38 +08:00
|
|
|
UnresolvedUsingTypenameDecl *D) {
|
|
|
|
VisitTypeDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->TypenameLocation = ReadSourceLocation(Record, Idx);
|
2011-02-25 08:36:19 +08:00
|
|
|
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-10-25 01:26:27 +08:00
|
|
|
void ASTDeclReader::ReadCXXDefinitionData(
|
2010-10-25 01:26:40 +08:00
|
|
|
struct CXXRecordDecl::DefinitionData &Data,
|
|
|
|
const RecordData &Record, unsigned &Idx) {
|
2012-02-15 01:54:36 +08:00
|
|
|
// Note: the caller has deserialized the IsLambda bit already.
|
2010-10-25 01:26:27 +08:00
|
|
|
Data.UserDeclaredConstructor = Record[Idx++];
|
2012-11-30 13:11:39 +08:00
|
|
|
Data.UserDeclaredSpecialMembers = Record[Idx++];
|
2010-10-25 01:26:27 +08:00
|
|
|
Data.Aggregate = Record[Idx++];
|
|
|
|
Data.PlainOldData = Record[Idx++];
|
|
|
|
Data.Empty = Record[Idx++];
|
|
|
|
Data.Polymorphic = Record[Idx++];
|
|
|
|
Data.Abstract = Record[Idx++];
|
2011-04-30 18:07:30 +08:00
|
|
|
Data.IsStandardLayout = Record[Idx++];
|
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:
1) It implemented all of the logic in RecordType by walking over every
base and field in a CXXRecordDecl and validating the constraints of
the standard. This made for very straightforward code, but is
extremely inefficient. It also is conceptually wrong, the logic tied
to the C++ definition of standard-layout classes should be in
CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
CXXRecordDecl, and at the completion of every C++ class, the
RecordType was queried to determine if it was a standard layout
class, and that state was cached. Two things went very very wrong
with this. First, the caching version of the query *was never
called*. Even within the recursive steps of the walk over all fields
and bases the caching variant was not called, making each query
a full *recursive* walk. Second, despite the cache not being used, it
was computed for every class declared, even when the trait was never
used in the program. This probably significantly regressed compile
time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).
The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.
The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.
It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.
Comments on any of these issues welcome.
llvm-svn: 130601
2011-04-30 17:17:45 +08:00
|
|
|
Data.HasNoNonEmptyBases = Record[Idx++];
|
|
|
|
Data.HasPrivateFields = Record[Idx++];
|
|
|
|
Data.HasProtectedFields = Record[Idx++];
|
|
|
|
Data.HasPublicFields = Record[Idx++];
|
2011-05-13 09:05:07 +08:00
|
|
|
Data.HasMutableFields = Record[Idx++];
|
2012-02-25 15:33:38 +08:00
|
|
|
Data.HasOnlyCMembers = Record[Idx++];
|
2012-05-07 09:07:30 +08:00
|
|
|
Data.HasInClassInitializer = Record[Idx++];
|
2012-12-08 10:01:17 +08:00
|
|
|
Data.HasUninitializedReferenceMember = Record[Idx++];
|
2012-12-08 16:32:28 +08:00
|
|
|
Data.NeedOverloadResolutionForMoveConstructor = Record[Idx++];
|
|
|
|
Data.NeedOverloadResolutionForMoveAssignment = Record[Idx++];
|
|
|
|
Data.NeedOverloadResolutionForDestructor = Record[Idx++];
|
|
|
|
Data.DefaultedMoveConstructorIsDeleted = Record[Idx++];
|
|
|
|
Data.DefaultedMoveAssignmentIsDeleted = Record[Idx++];
|
|
|
|
Data.DefaultedDestructorIsDeleted = Record[Idx++];
|
2012-11-30 13:11:39 +08:00
|
|
|
Data.HasTrivialSpecialMembers = Record[Idx++];
|
|
|
|
Data.HasIrrelevantDestructor = Record[Idx++];
|
2011-08-11 02:11:37 +08:00
|
|
|
Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
|
2012-02-25 15:33:38 +08:00
|
|
|
Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
|
|
|
|
Data.HasConstexprDefaultConstructor = Record[Idx++];
|
2011-04-24 10:49:34 +08:00
|
|
|
Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
|
2010-10-25 01:26:27 +08:00
|
|
|
Data.ComputedVisibleConversions = Record[Idx++];
|
2011-05-12 06:34:38 +08:00
|
|
|
Data.UserProvidedDefaultConstructor = Record[Idx++];
|
2012-11-30 13:11:39 +08:00
|
|
|
Data.DeclaredSpecialMembers = Record[Idx++];
|
2012-11-28 14:23:12 +08:00
|
|
|
Data.ImplicitCopyConstructorHasConstParam = Record[Idx++];
|
|
|
|
Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++];
|
|
|
|
Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++];
|
|
|
|
Data.HasDeclaredCopyAssignmentWithConstParam = Record[Idx++];
|
2011-08-31 21:59:56 +08:00
|
|
|
Data.FailedImplicitMoveConstructor = Record[Idx++];
|
|
|
|
Data.FailedImplicitMoveAssignment = Record[Idx++];
|
2011-01-23 02:11:02 +08:00
|
|
|
|
2010-10-25 01:26:27 +08:00
|
|
|
Data.NumBases = Record[Idx++];
|
2010-10-30 06:39:52 +08:00
|
|
|
if (Data.NumBases)
|
2011-08-04 08:01:48 +08:00
|
|
|
Data.Bases = Reader.readCXXBaseSpecifiers(F, Record, Idx);
|
2010-10-25 01:26:27 +08:00
|
|
|
Data.NumVBases = Record[Idx++];
|
2010-10-30 06:39:52 +08:00
|
|
|
if (Data.NumVBases)
|
2011-08-04 08:01:48 +08:00
|
|
|
Data.VBases = Reader.readCXXBaseSpecifiers(F, Record, Idx);
|
2010-10-30 06:39:52 +08:00
|
|
|
|
2011-07-22 06:35:25 +08:00
|
|
|
Reader.ReadUnresolvedSet(F, Data.Conversions, Record, Idx);
|
|
|
|
Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx);
|
2010-10-25 01:26:27 +08:00
|
|
|
assert(Data.Definition && "Data.Definition should be already set!");
|
2013-08-30 08:23:29 +08:00
|
|
|
Data.FirstFriend = ReadDeclID(Record, Idx);
|
|
|
|
|
2012-02-15 01:54:36 +08:00
|
|
|
if (Data.IsLambda) {
|
|
|
|
typedef LambdaExpr::Capture Capture;
|
|
|
|
CXXRecordDecl::LambdaDefinitionData &Lambda
|
|
|
|
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
|
2012-02-22 03:11:17 +08:00
|
|
|
Lambda.Dependent = Record[Idx++];
|
2012-02-15 01:54:36 +08:00
|
|
|
Lambda.NumCaptures = Record[Idx++];
|
|
|
|
Lambda.NumExplicitCaptures = Record[Idx++];
|
2012-02-21 03:44:39 +08:00
|
|
|
Lambda.ManglingNumber = Record[Idx++];
|
2012-02-21 08:37:24 +08:00
|
|
|
Lambda.ContextDecl = ReadDecl(Record, Idx);
|
2012-02-15 01:54:36 +08:00
|
|
|
Lambda.Captures
|
|
|
|
= (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
|
|
|
|
Capture *ToCapture = Lambda.Captures;
|
2012-09-19 09:18:11 +08:00
|
|
|
Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));
|
2012-02-15 01:54:36 +08:00
|
|
|
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
|
|
|
|
SourceLocation Loc = ReadSourceLocation(Record, Idx);
|
|
|
|
bool IsImplicit = Record[Idx++];
|
|
|
|
LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
|
2013-05-16 14:20:58 +08:00
|
|
|
switch (Kind) {
|
|
|
|
case LCK_This:
|
|
|
|
*ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation());
|
|
|
|
break;
|
|
|
|
case LCK_ByCopy:
|
|
|
|
case LCK_ByRef: {
|
|
|
|
VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
|
|
|
|
SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
*ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LCK_Init:
|
|
|
|
FieldDecl *Field = ReadDeclAs<FieldDecl>(Record, Idx);
|
|
|
|
*ToCapture++ = Capture(Field);
|
|
|
|
break;
|
|
|
|
}
|
2012-02-15 01:54:36 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-25 01:26:27 +08:00
|
|
|
}
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
|
|
|
RedeclarableResult Redecl = VisitRecordDeclImpl(D);
|
2010-10-20 08:11:15 +08:00
|
|
|
|
2012-01-16 02:17:48 +08:00
|
|
|
ASTContext &C = Reader.getContext();
|
2013-09-10 00:55:27 +08:00
|
|
|
bool WasDefinition = Record[Idx++];
|
|
|
|
if (WasDefinition) {
|
2012-02-15 01:54:36 +08:00
|
|
|
// Determine whether this is a lambda closure type, so that we can
|
|
|
|
// allocate the appropriate DefinitionData structure.
|
|
|
|
bool IsLambda = Record[Idx++];
|
|
|
|
if (IsLambda)
|
2012-09-19 09:18:11 +08:00
|
|
|
D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0,
|
|
|
|
false);
|
2012-02-15 01:54:36 +08:00
|
|
|
else
|
|
|
|
D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
|
2013-09-10 00:55:27 +08:00
|
|
|
|
|
|
|
ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
|
|
|
|
|
2012-01-16 02:08:05 +08:00
|
|
|
// Propagate the DefinitionData pointer to the canonical declaration, so
|
|
|
|
// that all other deserialized declarations will see it.
|
2013-09-10 00:55:27 +08:00
|
|
|
CXXRecordDecl *Canon = D->getCanonicalDecl();
|
|
|
|
if (Canon == D) {
|
|
|
|
// Nothing to do.
|
|
|
|
} else if (!Canon->DefinitionData) {
|
|
|
|
Canon->DefinitionData = D->DefinitionData;
|
|
|
|
|
|
|
|
// Note that we have deserialized a definition. Any declarations
|
|
|
|
// deserialized before this one will be be given the DefinitionData
|
|
|
|
// pointer at the end.
|
|
|
|
Reader.PendingDefinitions.insert(D);
|
|
|
|
} else {
|
|
|
|
// We have already deserialized a definition of this record. This
|
|
|
|
// definition is no longer really a definition. Note that the pre-existing
|
|
|
|
// definition is the *real* definition.
|
|
|
|
// FIXME: Check DefinitionData for consistency with prior definition.
|
|
|
|
Reader.MergedDeclContexts.insert(
|
|
|
|
std::make_pair(D, D->getCanonicalDecl()->DefinitionData->Definition));
|
|
|
|
D->IsCompleteDefinition = false;
|
|
|
|
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
|
|
|
|
}
|
2012-01-16 02:08:05 +08:00
|
|
|
} else {
|
|
|
|
// Propagate DefinitionData pointer from the canonical declaration.
|
2013-09-10 00:55:27 +08:00
|
|
|
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
|
2010-07-02 19:55:32 +08:00
|
|
|
}
|
|
|
|
|
2010-06-20 03:29:09 +08:00
|
|
|
enum CXXRecKind {
|
|
|
|
CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
|
|
|
|
};
|
|
|
|
switch ((CXXRecKind)Record[Idx++]) {
|
|
|
|
case CXXRecNotTemplate:
|
|
|
|
break;
|
|
|
|
case CXXRecTemplate:
|
2011-07-22 06:35:25 +08:00
|
|
|
D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
|
2010-06-20 03:29:09 +08:00
|
|
|
break;
|
|
|
|
case CXXRecMemberSpecialization: {
|
2011-07-22 06:35:25 +08:00
|
|
|
CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx);
|
2010-06-20 03:29:09 +08:00
|
|
|
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
|
2010-10-05 23:59:54 +08:00
|
|
|
SourceLocation POI = ReadSourceLocation(Record, Idx);
|
2010-09-13 19:45:25 +08:00
|
|
|
MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
|
|
|
|
MSI->setPointOfInstantiation(POI);
|
|
|
|
D->TemplateOrInstantiation = MSI;
|
2010-06-20 03:29:09 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-10-15 04:14:38 +08:00
|
|
|
|
2013-08-30 07:59:27 +08:00
|
|
|
// Lazily load the key function to avoid deserializing every method so we can
|
2010-10-15 04:14:38 +08:00
|
|
|
// compute it.
|
2013-09-10 00:55:27 +08:00
|
|
|
if (WasDefinition) {
|
|
|
|
DeclID KeyFn = ReadDeclID(Record, Idx);
|
|
|
|
if (KeyFn && D->IsCompleteDefinition)
|
2013-08-30 07:59:27 +08:00
|
|
|
C.KeyFunctions[D] = KeyFn;
|
2010-10-15 04:14:38 +08:00
|
|
|
}
|
2013-05-23 09:49:11 +08:00
|
|
|
|
|
|
|
return Redecl;
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitFunctionDecl(D);
|
2010-07-05 05:44:35 +08:00
|
|
|
unsigned NumOverridenMethods = Record[Idx++];
|
|
|
|
while (NumOverridenMethods--) {
|
|
|
|
// Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
|
|
|
|
// MD may be initializing.
|
2011-07-22 06:35:25 +08:00
|
|
|
if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx))
|
2011-09-10 05:34:22 +08:00
|
|
|
Reader.getContext().addOverriddenMethod(D, MD);
|
2010-07-05 05:44:35 +08:00
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitCXXMethodDecl(D);
|
2010-07-02 23:58:43 +08:00
|
|
|
|
|
|
|
D->IsExplicitSpecified = Record[Idx++];
|
2011-01-09 04:30:50 +08:00
|
|
|
llvm::tie(D->CtorInitializers, D->NumCtorInitializers)
|
|
|
|
= Reader.ReadCXXCtorInitializers(F, Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitCXXMethodDecl(D);
|
2010-07-02 23:58:43 +08:00
|
|
|
|
2011-07-22 06:35:25 +08:00
|
|
|
D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
|
2010-05-08 05:43:38 +08:00
|
|
|
VisitCXXMethodDecl(D);
|
2010-07-02 23:58:43 +08:00
|
|
|
D->IsExplicitSpecified = Record[Idx++];
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2011-12-03 07:23:56 +08:00
|
|
|
void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
|
|
|
|
VisitDecl(D);
|
|
|
|
D->ImportedAndComplete.setPointer(readModule(Record, Idx));
|
|
|
|
D->ImportedAndComplete.setInt(Record[Idx++]);
|
|
|
|
SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(D + 1);
|
|
|
|
for (unsigned I = 0, N = Record.back(); I != N; ++I)
|
|
|
|
StoredLocs[I] = ReadSourceLocation(Record, Idx);
|
2012-10-03 09:58:45 +08:00
|
|
|
++Idx; // The number of stored source locations.
|
2011-12-03 07:23:56 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
|
2010-06-05 13:09:32 +08:00
|
|
|
VisitDecl(D);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->setColonLoc(ReadSourceLocation(Record, Idx));
|
2010-06-05 13:09:32 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
|
2010-07-05 18:38:01 +08:00
|
|
|
VisitDecl(D);
|
2013-01-31 17:54:08 +08:00
|
|
|
if (Record[Idx++]) // hasFriendDecl
|
2011-07-22 06:35:25 +08:00
|
|
|
D->Friend = ReadDeclAs<NamedDecl>(Record, Idx);
|
2013-01-31 17:54:08 +08:00
|
|
|
else
|
|
|
|
D->Friend = GetTypeSourceInfo(Record, Idx);
|
|
|
|
for (unsigned i = 0; i != D->NumTPLists; ++i)
|
|
|
|
D->getTPLists()[i] = Reader.ReadTemplateParameterList(F, Record, Idx);
|
2013-08-30 08:23:29 +08:00
|
|
|
D->NextFriend = ReadDeclID(Record, Idx);
|
2010-10-16 14:59:13 +08:00
|
|
|
D->UnsupportedFriend = (Record[Idx++] != 0);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->FriendLoc = ReadSourceLocation(Record, Idx);
|
2010-06-30 06:47:00 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
|
2010-07-23 00:04:10 +08:00
|
|
|
VisitDecl(D);
|
|
|
|
unsigned NumParams = Record[Idx++];
|
|
|
|
D->NumParams = NumParams;
|
|
|
|
D->Params = new TemplateParameterList*[NumParams];
|
|
|
|
for (unsigned i = 0; i != NumParams; ++i)
|
2010-10-05 23:59:54 +08:00
|
|
|
D->Params[i] = Reader.ReadTemplateParameterList(F, Record, Idx);
|
2010-07-23 00:04:10 +08:00
|
|
|
if (Record[Idx++]) // HasFriendDecl
|
2011-07-22 06:35:25 +08:00
|
|
|
D->Friend = ReadDeclAs<NamedDecl>(Record, Idx);
|
2010-07-23 00:04:10 +08:00
|
|
|
else
|
2010-10-05 23:59:54 +08:00
|
|
|
D->Friend = GetTypeSourceInfo(Record, Idx);
|
|
|
|
D->FriendLoc = ReadSourceLocation(Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
2010-06-20 03:29:09 +08:00
|
|
|
VisitNamedDecl(D);
|
|
|
|
|
2011-07-22 06:35:25 +08:00
|
|
|
NamedDecl *TemplatedDecl = ReadDeclAs<NamedDecl>(Record, Idx);
|
2010-06-23 21:48:30 +08:00
|
|
|
TemplateParameterList* TemplateParams
|
2010-10-05 23:59:54 +08:00
|
|
|
= Reader.ReadTemplateParameterList(F, Record, Idx);
|
2010-06-20 03:29:09 +08:00
|
|
|
D->init(TemplatedDecl, TemplateParams);
|
2013-06-25 06:51:00 +08:00
|
|
|
|
|
|
|
// FIXME: If this is a redeclaration of a template from another module, handle
|
|
|
|
// inheritance of default template arguments.
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2012-01-07 06:05:37 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
2012-01-14 23:13:49 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(D);
|
2011-12-20 02:19:24 +08:00
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
// Make sure we've allocated the Common pointer first. We do this before
|
|
|
|
// VisitTemplateDecl so that getCommonPtr() can be used during initialization.
|
|
|
|
RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
|
|
|
|
if (!CanonD->Common) {
|
|
|
|
CanonD->Common = CanonD->newCommon(Reader.getContext());
|
|
|
|
Reader.PendingDefinitions.insert(CanonD);
|
|
|
|
}
|
|
|
|
D->Common = CanonD->Common;
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
// If this is the first declaration of the template, fill in the information
|
|
|
|
// for the 'common' pointer.
|
|
|
|
if (ThisDeclID == Redecl.getFirstID()) {
|
2010-07-30 00:11:51 +08:00
|
|
|
if (RedeclarableTemplateDecl *RTD
|
2011-12-22 09:48:48 +08:00
|
|
|
= ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
|
2010-07-30 00:11:51 +08:00
|
|
|
assert(RTD->getKind() == D->getKind() &&
|
|
|
|
"InstantiatedFromMemberTemplate kind mismatch");
|
2012-01-14 23:13:49 +08:00
|
|
|
D->setInstantiatedFromMemberTemplate(RTD);
|
2010-07-30 00:11:51 +08:00
|
|
|
if (Record[Idx++])
|
|
|
|
D->setMemberSpecialization();
|
|
|
|
}
|
|
|
|
}
|
2012-10-01 17:18:00 +08:00
|
|
|
|
2010-09-09 03:31:22 +08:00
|
|
|
VisitTemplateDecl(D);
|
|
|
|
D->IdentifierNamespace = Record[Idx++];
|
2012-10-01 17:18:00 +08:00
|
|
|
|
|
|
|
mergeRedeclarable(D, Redecl);
|
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
return Redecl;
|
2010-07-30 00:11:51 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
2012-01-14 23:13:49 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
2010-07-30 00:11:51 +08:00
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
if (ThisDeclID == Redecl.getFirstID()) {
|
2010-10-28 06:21:36 +08:00
|
|
|
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
|
|
|
|
// the specializations.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<serialization::DeclID, 2> SpecIDs;
|
2010-10-28 06:21:36 +08:00
|
|
|
SpecIDs.push_back(0);
|
|
|
|
|
|
|
|
// Specializations.
|
|
|
|
unsigned Size = Record[Idx++];
|
|
|
|
SpecIDs[0] += Size;
|
2011-07-22 06:35:25 +08:00
|
|
|
for (unsigned I = 0; I != Size; ++I)
|
|
|
|
SpecIDs.push_back(ReadDeclID(Record, Idx));
|
2010-10-28 06:21:36 +08:00
|
|
|
|
|
|
|
// Partial specializations.
|
|
|
|
Size = Record[Idx++];
|
|
|
|
SpecIDs[0] += Size;
|
2011-07-22 06:35:25 +08:00
|
|
|
for (unsigned I = 0; I != Size; ++I)
|
|
|
|
SpecIDs.push_back(ReadDeclID(Record, Idx));
|
2010-10-28 06:21:36 +08:00
|
|
|
|
2012-11-06 08:35:02 +08:00
|
|
|
ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
|
2010-10-28 06:21:36 +08:00
|
|
|
if (SpecIDs[0]) {
|
|
|
|
typedef serialization::DeclID DeclID;
|
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
// FIXME: Append specializations!
|
2010-10-28 06:21:36 +08:00
|
|
|
CommonPtr->LazySpecializations
|
2011-09-10 05:34:22 +08:00
|
|
|
= new (Reader.getContext()) DeclID [SpecIDs.size()];
|
2010-10-28 06:21:36 +08:00
|
|
|
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
|
|
|
|
SpecIDs.size() * sizeof(DeclID));
|
|
|
|
}
|
|
|
|
|
2012-11-06 08:35:02 +08:00
|
|
|
CommonPtr->InjectedClassNameType = Reader.readType(F, Record, Idx);
|
2010-06-20 03:29:09 +08:00
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2013-08-24 06:21:36 +08:00
|
|
|
/// TODO: Unify with ClassTemplateDecl version?
|
|
|
|
/// May require unifying ClassTemplateDecl and
|
|
|
|
/// VarTemplateDecl beyond TemplateDecl...
|
2013-08-06 09:03:05 +08:00
|
|
|
void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
|
|
|
|
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
|
|
|
|
|
|
|
if (ThisDeclID == Redecl.getFirstID()) {
|
2013-08-14 11:09:19 +08:00
|
|
|
// This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
|
2013-08-06 09:03:05 +08:00
|
|
|
// the specializations.
|
|
|
|
SmallVector<serialization::DeclID, 2> SpecIDs;
|
|
|
|
SpecIDs.push_back(0);
|
|
|
|
|
|
|
|
// Specializations.
|
|
|
|
unsigned Size = Record[Idx++];
|
|
|
|
SpecIDs[0] += Size;
|
|
|
|
for (unsigned I = 0; I != Size; ++I)
|
|
|
|
SpecIDs.push_back(ReadDeclID(Record, Idx));
|
|
|
|
|
|
|
|
// Partial specializations.
|
|
|
|
Size = Record[Idx++];
|
|
|
|
SpecIDs[0] += Size;
|
|
|
|
for (unsigned I = 0; I != Size; ++I)
|
|
|
|
SpecIDs.push_back(ReadDeclID(Record, Idx));
|
|
|
|
|
|
|
|
VarTemplateDecl::Common *CommonPtr = D->getCommonPtr();
|
|
|
|
if (SpecIDs[0]) {
|
|
|
|
typedef serialization::DeclID DeclID;
|
|
|
|
|
|
|
|
// FIXME: Append specializations!
|
|
|
|
CommonPtr->LazySpecializations =
|
|
|
|
new (Reader.getContext()) DeclID[SpecIDs.size()];
|
|
|
|
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
|
|
|
|
SpecIDs.size() * sizeof(DeclID));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
|
|
|
ClassTemplateSpecializationDecl *D) {
|
|
|
|
RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D);
|
2010-09-13 19:45:32 +08:00
|
|
|
|
2011-09-10 05:34:22 +08:00
|
|
|
ASTContext &C = Reader.getContext();
|
2011-07-22 06:35:25 +08:00
|
|
|
if (Decl *InstD = ReadDecl(Record, Idx)) {
|
2010-06-23 21:48:30 +08:00
|
|
|
if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
|
2010-09-13 19:45:32 +08:00
|
|
|
D->SpecializedTemplate = CTD;
|
2010-06-23 21:48:30 +08:00
|
|
|
} else {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
2010-10-05 23:59:54 +08:00
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
2010-09-13 19:45:32 +08:00
|
|
|
TemplateArgumentList *ArgList
|
2010-11-08 07:05:16 +08:00
|
|
|
= TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
|
|
|
|
TemplArgs.size());
|
2010-09-13 19:45:32 +08:00
|
|
|
ClassTemplateSpecializationDecl::SpecializedPartialSpecialization *PS
|
|
|
|
= new (C) ClassTemplateSpecializationDecl::
|
|
|
|
SpecializedPartialSpecialization();
|
|
|
|
PS->PartialSpecialization
|
|
|
|
= cast<ClassTemplatePartialSpecializationDecl>(InstD);
|
|
|
|
PS->TemplateArgs = ArgList;
|
|
|
|
D->SpecializedTemplate = PS;
|
2010-06-23 21:48:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
2010-10-05 23:59:54 +08:00
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
2010-11-08 07:05:16 +08:00
|
|
|
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
|
|
|
|
TemplArgs.size());
|
2010-10-05 23:59:54 +08:00
|
|
|
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
|
2010-09-13 19:45:32 +08:00
|
|
|
D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
|
2012-10-01 15:34:47 +08:00
|
|
|
|
|
|
|
bool writtenAsCanonicalDecl = Record[Idx++];
|
|
|
|
if (writtenAsCanonicalDecl) {
|
2011-07-22 06:35:25 +08:00
|
|
|
ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx);
|
2012-10-01 15:34:47 +08:00
|
|
|
if (D->isCanonicalDecl()) { // It's kept in the folding set.
|
2013-09-10 00:55:27 +08:00
|
|
|
// Set this as, or find, the canonical declaration for this specialization
|
|
|
|
ClassTemplateSpecializationDecl *CanonSpec;
|
2013-06-25 09:25:15 +08:00
|
|
|
if (ClassTemplatePartialSpecializationDecl *Partial =
|
|
|
|
dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
|
2013-09-10 00:55:27 +08:00
|
|
|
CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations
|
2013-06-25 09:25:15 +08:00
|
|
|
.GetOrInsertNode(Partial);
|
2012-10-01 15:34:47 +08:00
|
|
|
} else {
|
2013-09-10 00:55:27 +08:00
|
|
|
CanonSpec =
|
|
|
|
CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
|
|
|
|
}
|
|
|
|
// If there was already a canonical specialization, merge into it.
|
|
|
|
if (CanonSpec != D) {
|
|
|
|
mergeRedeclarable<TagDecl>(D, CanonSpec, Redecl);
|
|
|
|
|
|
|
|
// This declaration might be a definition. Merge with any existing
|
|
|
|
// definition.
|
|
|
|
if (D->DefinitionData) {
|
|
|
|
if (!CanonSpec->DefinitionData) {
|
|
|
|
CanonSpec->DefinitionData = D->DefinitionData;
|
|
|
|
} else {
|
|
|
|
// FIXME: Check DefinitionData for consistency with prior definition
|
|
|
|
Reader.PendingDefinitions.erase(D);
|
|
|
|
Reader.MergedDeclContexts.insert(
|
|
|
|
std::make_pair(D, CanonSpec->DefinitionData->Definition));
|
|
|
|
D->IsCompleteDefinition = false;
|
|
|
|
D->DefinitionData = CanonSpec->DefinitionData;
|
|
|
|
}
|
|
|
|
}
|
2012-10-01 15:34:47 +08:00
|
|
|
}
|
2010-07-10 05:11:43 +08:00
|
|
|
}
|
|
|
|
}
|
2013-05-23 09:49:11 +08:00
|
|
|
|
2013-09-10 00:55:27 +08:00
|
|
|
// Explicit info.
|
|
|
|
if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
|
|
|
|
ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo
|
|
|
|
= new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
|
|
|
|
ExplicitInfo->TypeAsWritten = TyInfo;
|
|
|
|
ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
D->ExplicitInfo = ExplicitInfo;
|
|
|
|
}
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
return Redecl;
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
|
2010-05-08 05:43:38 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *D) {
|
2013-05-23 09:49:11 +08:00
|
|
|
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
|
2010-06-23 21:48:30 +08:00
|
|
|
|
2010-10-05 23:59:54 +08:00
|
|
|
D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
|
2013-08-10 15:24:53 +08:00
|
|
|
D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx);
|
2010-09-13 19:45:41 +08:00
|
|
|
|
2010-06-23 21:48:30 +08:00
|
|
|
// These are read/set from/to the first declaration.
|
2013-05-23 09:49:11 +08:00
|
|
|
if (ThisDeclID == Redecl.getFirstID()) {
|
2010-09-13 19:45:41 +08:00
|
|
|
D->InstantiatedFromMember.setPointer(
|
2011-07-22 06:35:25 +08:00
|
|
|
ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx));
|
2010-09-13 19:45:41 +08:00
|
|
|
D->InstantiatedFromMember.setInt(Record[Idx++]);
|
2010-06-23 21:48:30 +08:00
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2011-08-31 21:59:56 +08:00
|
|
|
void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
|
|
|
|
ClassScopeFunctionSpecializationDecl *D) {
|
2011-08-17 09:06:54 +08:00
|
|
|
VisitDecl(D);
|
|
|
|
D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx);
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
2012-01-14 23:13:49 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
2010-06-22 17:55:07 +08:00
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
if (ThisDeclID == Redecl.getFirstID()) {
|
2010-06-22 17:55:07 +08:00
|
|
|
// This FunctionTemplateDecl owns a CommonPtr; read it.
|
|
|
|
|
2013-06-28 12:37:53 +08:00
|
|
|
// Read the function specialization declaration IDs. The specializations
|
|
|
|
// themselves will be loaded if they're needed.
|
|
|
|
if (unsigned NumSpecs = Record[Idx++]) {
|
|
|
|
// FIXME: Append specializations!
|
|
|
|
FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr();
|
|
|
|
CommonPtr->LazySpecializations = new (Reader.getContext())
|
|
|
|
serialization::DeclID[NumSpecs + 1];
|
|
|
|
CommonPtr->LazySpecializations[0] = NumSpecs;
|
|
|
|
for (unsigned I = 0; I != NumSpecs; ++I)
|
|
|
|
CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx);
|
|
|
|
}
|
2010-06-22 17:55:07 +08:00
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2013-08-24 06:21:36 +08:00
|
|
|
/// TODO: Unify with ClassTemplateSpecializationDecl version?
|
|
|
|
/// May require unifying ClassTemplate(Partial)SpecializationDecl and
|
|
|
|
/// VarTemplate(Partial)SpecializationDecl with a new data
|
|
|
|
/// structure Template(Partial)SpecializationDecl, and
|
|
|
|
/// using Template(Partial)SpecializationDecl as input type.
|
2013-08-06 09:03:05 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|
|
|
VarTemplateSpecializationDecl *D) {
|
|
|
|
RedeclarableResult Redecl = VisitVarDeclImpl(D);
|
|
|
|
|
|
|
|
ASTContext &C = Reader.getContext();
|
|
|
|
if (Decl *InstD = ReadDecl(Record, Idx)) {
|
|
|
|
if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
|
|
|
|
D->SpecializedTemplate = VTD;
|
|
|
|
} else {
|
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
|
|
|
TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(
|
|
|
|
C, TemplArgs.data(), TemplArgs.size());
|
|
|
|
VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS =
|
|
|
|
new (C)
|
|
|
|
VarTemplateSpecializationDecl::SpecializedPartialSpecialization();
|
|
|
|
PS->PartialSpecialization =
|
|
|
|
cast<VarTemplatePartialSpecializationDecl>(InstD);
|
|
|
|
PS->TemplateArgs = ArgList;
|
|
|
|
D->SpecializedTemplate = PS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Explicit info.
|
|
|
|
if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
|
|
|
|
VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo =
|
|
|
|
new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
|
|
|
|
ExplicitInfo->TypeAsWritten = TyInfo;
|
|
|
|
ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
D->ExplicitInfo = ExplicitInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
|
|
|
D->TemplateArgs =
|
|
|
|
TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
|
|
|
|
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
|
|
|
|
D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
|
|
|
|
|
|
|
|
bool writtenAsCanonicalDecl = Record[Idx++];
|
|
|
|
if (writtenAsCanonicalDecl) {
|
|
|
|
VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(Record, Idx);
|
|
|
|
if (D->isCanonicalDecl()) { // It's kept in the folding set.
|
|
|
|
if (VarTemplatePartialSpecializationDecl *Partial =
|
|
|
|
dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
|
|
|
|
CanonPattern->getCommonPtr()->PartialSpecializations
|
|
|
|
.GetOrInsertNode(Partial);
|
|
|
|
} else {
|
|
|
|
CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Redecl;
|
|
|
|
}
|
|
|
|
|
2013-08-24 06:21:36 +08:00
|
|
|
/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
|
|
|
|
/// May require unifying ClassTemplate(Partial)SpecializationDecl and
|
|
|
|
/// VarTemplate(Partial)SpecializationDecl with a new data
|
|
|
|
/// structure Template(Partial)SpecializationDecl, and
|
|
|
|
/// using Template(Partial)SpecializationDecl as input type.
|
2013-08-06 09:03:05 +08:00
|
|
|
void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
|
|
|
|
VarTemplatePartialSpecializationDecl *D) {
|
|
|
|
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
|
|
|
|
|
|
|
|
D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
|
2013-08-10 15:24:53 +08:00
|
|
|
D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx);
|
2013-08-06 09:03:05 +08:00
|
|
|
|
|
|
|
// These are read/set from/to the first declaration.
|
|
|
|
if (ThisDeclID == Redecl.getFirstID()) {
|
|
|
|
D->InstantiatedFromMember.setPointer(
|
|
|
|
ReadDeclAs<VarTemplatePartialSpecializationDecl>(Record, Idx));
|
|
|
|
D->InstantiatedFromMember.setInt(Record[Idx++]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
|
2010-06-20 03:29:09 +08:00
|
|
|
VisitTypeDecl(D);
|
|
|
|
|
|
|
|
D->setDeclaredWithTypename(Record[Idx++]);
|
|
|
|
|
|
|
|
bool Inherited = Record[Idx++];
|
2010-10-05 23:59:54 +08:00
|
|
|
TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx);
|
2010-06-20 03:29:09 +08:00
|
|
|
D->setDefaultArgument(DefArg, Inherited);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
2011-02-09 09:13:10 +08:00
|
|
|
VisitDeclaratorDecl(D);
|
2010-06-26 00:25:09 +08:00
|
|
|
// TemplateParmPosition.
|
|
|
|
D->setDepth(Record[Idx++]);
|
|
|
|
D->setPosition(Record[Idx++]);
|
2011-01-20 04:10:05 +08:00
|
|
|
if (D->isExpandedParameterPack()) {
|
|
|
|
void **Data = reinterpret_cast<void **>(D + 1);
|
|
|
|
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
|
2011-07-22 08:38:23 +08:00
|
|
|
Data[2*I] = Reader.readType(F, Record, Idx).getAsOpaquePtr();
|
2011-01-20 04:10:05 +08:00
|
|
|
Data[2*I + 1] = GetTypeSourceInfo(Record, Idx);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Rest of NonTypeTemplateParmDecl.
|
|
|
|
D->ParameterPack = Record[Idx++];
|
|
|
|
if (Record[Idx++]) {
|
|
|
|
Expr *DefArg = Reader.ReadExpr(F);
|
|
|
|
bool Inherited = Record[Idx++];
|
|
|
|
D->setDefaultArgument(DefArg, Inherited);
|
|
|
|
}
|
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
2010-07-09 01:12:57 +08:00
|
|
|
VisitTemplateDecl(D);
|
|
|
|
// TemplateParmPosition.
|
|
|
|
D->setDepth(Record[Idx++]);
|
|
|
|
D->setPosition(Record[Idx++]);
|
2012-09-07 10:06:42 +08:00
|
|
|
if (D->isExpandedParameterPack()) {
|
|
|
|
void **Data = reinterpret_cast<void **>(D + 1);
|
|
|
|
for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
|
|
|
|
I != N; ++I)
|
|
|
|
Data[I] = Reader.ReadTemplateParameterList(F, Record, Idx);
|
|
|
|
} else {
|
|
|
|
// Rest of TemplateTemplateParmDecl.
|
|
|
|
TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(F, Record, Idx);
|
|
|
|
bool IsInherited = Record[Idx++];
|
|
|
|
D->setDefaultArgument(Arg, IsInherited);
|
|
|
|
D->ParameterPack = Record[Idx++];
|
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2011-05-06 05:57:07 +08:00
|
|
|
void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
|
|
|
|
VisitRedeclarableTemplateDecl(D);
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
2010-07-23 01:28:12 +08:00
|
|
|
VisitDecl(D);
|
2012-07-12 06:37:56 +08:00
|
|
|
D->AssertExprAndFailed.setPointer(Reader.ReadExpr(F));
|
|
|
|
D->AssertExprAndFailed.setInt(Record[Idx++]);
|
2010-10-05 23:59:54 +08:00
|
|
|
D->Message = cast<StringLiteral>(Reader.ReadExpr(F));
|
2011-03-09 00:41:52 +08:00
|
|
|
D->RParenLoc = ReadSourceLocation(Record, Idx);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2013-02-23 01:15:32 +08:00
|
|
|
void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
|
|
|
|
VisitDecl(D);
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
std::pair<uint64_t, uint64_t>
|
2010-08-19 07:56:48 +08:00
|
|
|
ASTDeclReader::VisitDeclContext(DeclContext *DC) {
|
2009-04-27 13:27:42 +08:00
|
|
|
uint64_t LexicalOffset = Record[Idx++];
|
|
|
|
uint64_t VisibleOffset = Record[Idx++];
|
|
|
|
return std::make_pair(LexicalOffset, VisibleOffset);
|
|
|
|
}
|
|
|
|
|
2010-08-04 01:30:10 +08:00
|
|
|
template <typename T>
|
2011-12-22 09:48:48 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
2012-01-16 00:58:34 +08:00
|
|
|
DeclID FirstDeclID = ReadDeclID(Record, Idx);
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
// 0 indicates that this declaration was the only declaration of its entity,
|
|
|
|
// and is used for space optimization.
|
|
|
|
if (FirstDeclID == 0)
|
2011-12-20 02:19:24 +08:00
|
|
|
FirstDeclID = ThisDeclID;
|
2012-01-16 00:58:34 +08:00
|
|
|
|
|
|
|
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
|
|
|
|
if (FirstDecl != D) {
|
2011-02-12 15:50:47 +08:00
|
|
|
// We delay loading of the redeclaration chain to avoid deeply nested calls.
|
|
|
|
// We temporarily set the first (canonical) declaration as the previous one
|
|
|
|
// which is the one that matters and mark the real previous DeclID to be
|
|
|
|
// loaded & attached later on.
|
2012-05-29 03:38:42 +08:00
|
|
|
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
|
2012-01-16 00:58:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Note that this declaration has been deserialized.
|
|
|
|
Reader.RedeclsDeserialized.insert(static_cast<T *>(D));
|
|
|
|
|
|
|
|
// The result structure takes care to note that we need to load the
|
2011-12-22 09:48:48 +08:00
|
|
|
// other declaration chains for this ID.
|
2013-01-22 00:16:40 +08:00
|
|
|
return RedeclarableResult(Reader, FirstDeclID,
|
|
|
|
static_cast<T *>(D)->getKind());
|
2010-08-04 01:30:10 +08:00
|
|
|
}
|
|
|
|
|
2012-01-04 01:27:13 +08:00
|
|
|
/// \brief Attempts to merge the given declaration (D) with another declaration
|
|
|
|
/// of the same entity.
|
|
|
|
template<typename T>
|
2013-09-10 00:55:27 +08:00
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
|
2012-01-04 01:27:13 +08:00
|
|
|
RedeclarableResult &Redecl) {
|
2012-01-04 01:31:38 +08:00
|
|
|
// If modules are not available, there is no reason to perform this merge.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!Reader.getContext().getLangOpts().Modules)
|
2012-01-04 01:31:38 +08:00
|
|
|
return;
|
2013-09-10 00:55:27 +08:00
|
|
|
|
|
|
|
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
|
|
|
|
if (T *Existing = ExistingRes)
|
|
|
|
mergeRedeclarable(D, Existing, Redecl);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Attempts to merge the given declaration (D) with another declaration
|
|
|
|
/// of the same entity.
|
|
|
|
template<typename T>
|
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing,
|
|
|
|
RedeclarableResult &Redecl) {
|
|
|
|
T *ExistingCanon = Existing->getCanonicalDecl();
|
|
|
|
T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
|
|
|
|
if (ExistingCanon != DCanon) {
|
|
|
|
// Have our redeclaration link point back at the canonical declaration
|
|
|
|
// of the existing declaration, so that this declaration has the
|
|
|
|
// appropriate canonical declaration.
|
|
|
|
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
|
|
|
|
|
|
|
|
// When we merge a namespace, update its pointer to the first namespace.
|
|
|
|
if (NamespaceDecl *Namespace
|
|
|
|
= dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
|
|
|
|
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
|
|
|
|
static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't introduce DCanon into the set of pending declaration chains.
|
|
|
|
Redecl.suppress();
|
|
|
|
|
|
|
|
// Introduce ExistingCanon into the set of pending declaration chains,
|
|
|
|
// if in fact it came from a module file.
|
|
|
|
if (ExistingCanon->isFromASTFile()) {
|
|
|
|
GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID();
|
|
|
|
assert(ExistingCanonID && "Unrecorded canonical declaration ID?");
|
|
|
|
if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID))
|
|
|
|
Reader.PendingDeclChains.push_back(ExistingCanonID);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this declaration was the canonical declaration, make a note of
|
|
|
|
// that. We accept the linear algorithm here because the number of
|
|
|
|
// unique canonical declarations of an entity should always be tiny.
|
|
|
|
if (DCanon == static_cast<T*>(D)) {
|
|
|
|
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
|
|
|
|
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
|
|
|
|
== Merged.end())
|
|
|
|
Merged.push_back(Redecl.getFirstID());
|
|
|
|
|
|
|
|
// If ExistingCanon did not come from a module file, introduce the
|
|
|
|
// first declaration that *does* come from a module file to the
|
|
|
|
// set of pending declaration chains, so that we merge this
|
|
|
|
// declaration.
|
|
|
|
if (!ExistingCanon->isFromASTFile() &&
|
|
|
|
Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
|
|
|
|
Reader.PendingDeclChains.push_back(Merged[0]);
|
2012-01-04 01:27:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:34:35 +08:00
|
|
|
void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
|
|
|
|
VisitDecl(D);
|
|
|
|
unsigned NumVars = D->varlist_size();
|
2013-05-13 12:18:18 +08:00
|
|
|
SmallVector<Expr *, 16> Vars;
|
2013-03-22 14:34:35 +08:00
|
|
|
Vars.reserve(NumVars);
|
|
|
|
for (unsigned i = 0; i != NumVars; ++i) {
|
2013-05-13 12:18:18 +08:00
|
|
|
Vars.push_back(Reader.ReadExpr(F));
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
|
|
|
D->setVars(Vars);
|
|
|
|
}
|
|
|
|
|
2009-04-27 13:27:42 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2009-04-27 14:01:06 +08:00
|
|
|
// Attribute Reading
|
2009-04-27 13:27:42 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-04-27 14:01:06 +08:00
|
|
|
/// \brief Reads attributes from the current stream position.
|
2011-12-01 07:21:26 +08:00
|
|
|
void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs,
|
2010-10-19 03:20:11 +08:00
|
|
|
const RecordData &Record, unsigned &Idx) {
|
|
|
|
for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) {
|
2009-04-27 14:01:06 +08:00
|
|
|
Attr *New = 0;
|
2010-06-17 07:43:53 +08:00
|
|
|
attr::Kind Kind = (attr::Kind)Record[Idx++];
|
2011-09-14 00:05:58 +08:00
|
|
|
SourceRange Range = ReadSourceRange(F, Record, Idx);
|
2009-04-27 14:01:06 +08:00
|
|
|
|
2010-08-19 07:23:40 +08:00
|
|
|
#include "clang/Serialization/AttrPCHRead.inc"
|
2009-04-27 14:01:06 +08:00
|
|
|
|
|
|
|
assert(New && "Unable to decode attribute?");
|
2010-08-19 07:23:40 +08:00
|
|
|
Attrs.push_back(New);
|
2009-04-27 14:01:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-08-19 07:56:43 +08:00
|
|
|
// ASTReader Implementation
|
2009-04-27 14:01:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2009-04-27 13:27:42 +08:00
|
|
|
|
|
|
|
/// \brief Note that we have loaded the declaration with the given
|
|
|
|
/// Index.
|
2009-09-09 23:08:12 +08:00
|
|
|
///
|
2009-04-27 13:27:42 +08:00
|
|
|
/// This routine notes that this declaration has already been loaded,
|
|
|
|
/// so that future GetDecl calls will return this declaration rather
|
|
|
|
/// than trying to load a new declaration.
|
2010-08-19 07:56:43 +08:00
|
|
|
inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
|
2009-04-27 13:27:42 +08:00
|
|
|
assert(!DeclsLoaded[Index] && "Decl loaded twice?");
|
|
|
|
DeclsLoaded[Index] = D;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// \brief Determine whether the consumer will be interested in seeing
|
|
|
|
/// this declaration (via HandleTopLevelDecl).
|
|
|
|
///
|
|
|
|
/// This routine should return true for anything that might affect
|
|
|
|
/// code generation, e.g., inline function definitions, Objective-C
|
|
|
|
/// declarations with metadata, etc.
|
2012-10-10 01:21:28 +08:00
|
|
|
static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
|
2011-09-14 05:35:00 +08:00
|
|
|
// An ObjCMethodDecl is never considered as "interesting" because its
|
|
|
|
// implementation container always is.
|
|
|
|
|
2011-09-10 08:22:34 +08:00
|
|
|
if (isa<FileScopeAsmDecl>(D) ||
|
|
|
|
isa<ObjCProtocolDecl>(D) ||
|
|
|
|
isa<ObjCImplDecl>(D))
|
2009-09-17 11:06:44 +08:00
|
|
|
return true;
|
2009-04-27 13:27:42 +08:00
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(D))
|
2010-08-05 17:47:59 +08:00
|
|
|
return Var->isFileVarDecl() &&
|
|
|
|
Var->isThisDeclarationADefinition() == VarDecl::Definition;
|
2009-04-27 13:27:42 +08:00
|
|
|
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
|
2012-10-10 01:21:28 +08:00
|
|
|
return Func->doesThisDeclarationHaveABody() || HasBody;
|
2011-09-10 08:22:34 +08:00
|
|
|
|
|
|
|
return false;
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2011-07-20 08:27:43 +08:00
|
|
|
/// \brief Get the correct cursor and offset for loading a declaration.
|
2010-08-19 07:56:43 +08:00
|
|
|
ASTReader::RecordLocation
|
2011-10-28 02:47:35 +08:00
|
|
|
ASTReader::DeclCursorForID(DeclID ID, unsigned &RawLocation) {
|
2010-08-13 08:28:03 +08:00
|
|
|
// See if there's an override.
|
|
|
|
DeclReplacementMap::iterator It = ReplacedDecls.find(ID);
|
2011-10-31 15:20:15 +08:00
|
|
|
if (It != ReplacedDecls.end()) {
|
|
|
|
RawLocation = It->second.RawLoc;
|
|
|
|
return RecordLocation(It->second.Mod, It->second.Offset);
|
|
|
|
}
|
2010-08-13 08:28:03 +08:00
|
|
|
|
2011-07-20 08:27:43 +08:00
|
|
|
GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID);
|
|
|
|
assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
|
2011-12-01 07:21:26 +08:00
|
|
|
ModuleFile *M = I->second;
|
2011-10-28 02:47:35 +08:00
|
|
|
const DeclOffset &
|
|
|
|
DOffs = M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS];
|
|
|
|
RawLocation = DOffs.Loc;
|
|
|
|
return RecordLocation(M, DOffs.BitOffset);
|
2010-07-21 06:46:15 +08:00
|
|
|
}
|
|
|
|
|
Introduce a global bit-offset continuous range map into the ASTReader,
so that we have one, simple way to map from global bit offsets to
local bit offsets. Eliminates a number of loops over the chain, and
generalizes for more interesting bit remappings.
Also, as an amusing oddity, we were computing global bit offsets
*backwards* for preprocessed entities (e.g., the directly included PCH
file in the chain would start at offset zero, rather than the original
PCH that occurs first in translation unit). Even more amusingly, it
made precompiled preambles work, because we were forgetting to adjust
the local bit offset to a global bit offset when storing preprocessed
entity offsets in the ASTUnit. Two wrongs made a right, and now
they're both right.
llvm-svn: 135750
2011-07-22 14:10:01 +08:00
|
|
|
ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) {
|
2011-12-01 07:21:26 +08:00
|
|
|
ContinuousRangeMap<uint64_t, ModuleFile*, 4>::iterator I
|
Introduce a global bit-offset continuous range map into the ASTReader,
so that we have one, simple way to map from global bit offsets to
local bit offsets. Eliminates a number of loops over the chain, and
generalizes for more interesting bit remappings.
Also, as an amusing oddity, we were computing global bit offsets
*backwards* for preprocessed entities (e.g., the directly included PCH
file in the chain would start at offset zero, rather than the original
PCH that occurs first in translation unit). Even more amusingly, it
made precompiled preambles work, because we were forgetting to adjust
the local bit offset to a global bit offset when storing preprocessed
entity offsets in the ASTUnit. Two wrongs made a right, and now
they're both right.
llvm-svn: 135750
2011-07-22 14:10:01 +08:00
|
|
|
= GlobalBitOffsetsMap.find(GlobalOffset);
|
|
|
|
|
|
|
|
assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map");
|
|
|
|
return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset);
|
|
|
|
}
|
|
|
|
|
2011-12-01 07:21:26 +08:00
|
|
|
uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) {
|
2011-08-04 08:01:48 +08:00
|
|
|
return LocalOffset + M.GlobalBitOffset;
|
|
|
|
}
|
|
|
|
|
2013-06-25 06:51:00 +08:00
|
|
|
static bool isSameTemplateParameterList(const TemplateParameterList *X,
|
|
|
|
const TemplateParameterList *Y);
|
|
|
|
|
|
|
|
/// \brief Determine whether two template parameters are similar enough
|
|
|
|
/// that they may be used in declarations of the same template.
|
|
|
|
static bool isSameTemplateParameter(const NamedDecl *X,
|
|
|
|
const NamedDecl *Y) {
|
|
|
|
if (X->getKind() != Y->getKind())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (const TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
|
|
|
|
const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y);
|
|
|
|
return TX->isParameterPack() == TY->isParameterPack();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
|
|
|
|
const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y);
|
|
|
|
return TX->isParameterPack() == TY->isParameterPack() &&
|
|
|
|
TX->getASTContext().hasSameType(TX->getType(), TY->getType());
|
|
|
|
}
|
|
|
|
|
|
|
|
const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X);
|
|
|
|
const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y);
|
|
|
|
return TX->isParameterPack() == TY->isParameterPack() &&
|
|
|
|
isSameTemplateParameterList(TX->getTemplateParameters(),
|
|
|
|
TY->getTemplateParameters());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Determine whether two template parameter lists are similar enough
|
|
|
|
/// that they may be used in declarations of the same template.
|
|
|
|
static bool isSameTemplateParameterList(const TemplateParameterList *X,
|
|
|
|
const TemplateParameterList *Y) {
|
|
|
|
if (X->size() != Y->size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (unsigned I = 0, N = X->size(); I != N; ++I)
|
|
|
|
if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
/// \brief Determine whether the two declarations refer to the same entity.
|
|
|
|
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
|
|
|
|
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
|
|
|
|
|
|
|
|
if (X == Y)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Must be in the same context.
|
|
|
|
if (!X->getDeclContext()->getRedeclContext()->Equals(
|
|
|
|
Y->getDeclContext()->getRedeclContext()))
|
|
|
|
return false;
|
2012-01-05 00:44:10 +08:00
|
|
|
|
|
|
|
// Two typedefs refer to the same entity if they have the same underlying
|
|
|
|
// type.
|
|
|
|
if (TypedefNameDecl *TypedefX = dyn_cast<TypedefNameDecl>(X))
|
|
|
|
if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y))
|
|
|
|
return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(),
|
|
|
|
TypedefY->getUnderlyingType());
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-01-05 00:44:10 +08:00
|
|
|
// Must have the same kind.
|
|
|
|
if (X->getKind() != Y->getKind())
|
|
|
|
return false;
|
|
|
|
|
2012-01-02 05:47:52 +08:00
|
|
|
// Objective-C classes and protocols with the same name always match.
|
|
|
|
if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
|
2011-12-22 09:48:48 +08:00
|
|
|
return true;
|
2013-05-23 09:49:11 +08:00
|
|
|
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(X)) {
|
2013-09-10 00:55:27 +08:00
|
|
|
// No need to handle these here: we merge them when adding them to the
|
|
|
|
// template.
|
2013-05-23 09:49:11 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-09-10 00:55:27 +08:00
|
|
|
|
2012-01-04 06:46:00 +08:00
|
|
|
// Compatible tags match.
|
2012-09-01 06:18:20 +08:00
|
|
|
if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
|
|
|
|
TagDecl *TagY = cast<TagDecl>(Y);
|
|
|
|
return (TagX->getTagKind() == TagY->getTagKind()) ||
|
|
|
|
((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class ||
|
|
|
|
TagX->getTagKind() == TTK_Interface) &&
|
|
|
|
(TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class ||
|
|
|
|
TagY->getTagKind() == TTK_Interface));
|
|
|
|
}
|
2013-06-24 12:45:28 +08:00
|
|
|
|
2012-09-01 06:18:20 +08:00
|
|
|
// Functions with the same type and linkage match.
|
2013-06-24 12:45:28 +08:00
|
|
|
// FIXME: This needs to cope with function template specializations,
|
|
|
|
// merging of prototyped/non-prototyped functions, etc.
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
|
|
|
|
FunctionDecl *FuncY = cast<FunctionDecl>(Y);
|
2013-05-13 08:12:11 +08:00
|
|
|
return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) &&
|
Implement declaration merging for non-template functions from
different modules. This implementation is a first approximation of
what we want, using only the function type to determine
equivalence. Later, we'll want to deal with some of the more subtle
issues, including:
- C allows a prototyped declaration and a non-prototyped declaration
to be merged, which we should support
- We may want to ignore the return type when merging, then
complain if the return types differ. Or, we may want to leave it
as it us, so that we only complain if overload resolution
eventually fails.
- C++ non-static member functions need to consider cv-qualifiers
and ref-qualifiers.
- Function templates need to consider the template parameters and
return type.
- Function template specializations will have special rules.
- We can now (accidentally!) end up overloading in C, even without
the "overloadable" attribute, and will need to detect this at some
point.
The actual detection of "is this an overload?" is implemented by
Sema::IsOverload(), which will need to be moved into the AST library
for re-use here. That will be a future refactor.
llvm-svn: 147534
2012-01-05 01:13:46 +08:00
|
|
|
FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType());
|
|
|
|
}
|
2012-10-01 17:18:00 +08:00
|
|
|
|
2012-01-05 01:21:36 +08:00
|
|
|
// Variables with the same type and linkage match.
|
|
|
|
if (VarDecl *VarX = dyn_cast<VarDecl>(X)) {
|
|
|
|
VarDecl *VarY = cast<VarDecl>(Y);
|
2013-05-13 08:12:11 +08:00
|
|
|
return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) &&
|
2012-01-05 01:21:36 +08:00
|
|
|
VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
|
|
|
|
}
|
2013-06-24 12:45:28 +08:00
|
|
|
|
2012-01-10 01:30:44 +08:00
|
|
|
// Namespaces with the same name and inlinedness match.
|
|
|
|
if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
|
|
|
|
NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y);
|
|
|
|
return NamespaceX->isInline() == NamespaceY->isInline();
|
|
|
|
}
|
2012-10-01 17:18:00 +08:00
|
|
|
|
2013-06-24 12:45:28 +08:00
|
|
|
// Identical template names and kinds match if their template parameter lists
|
|
|
|
// and patterns match.
|
|
|
|
if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) {
|
2013-06-25 06:51:00 +08:00
|
|
|
TemplateDecl *TemplateY = cast<TemplateDecl>(Y);
|
2013-06-24 12:45:28 +08:00
|
|
|
return isSameEntity(TemplateX->getTemplatedDecl(),
|
2013-06-25 06:51:00 +08:00
|
|
|
TemplateY->getTemplatedDecl()) &&
|
|
|
|
isSameTemplateParameterList(TemplateX->getTemplateParameters(),
|
|
|
|
TemplateY->getTemplateParameters());
|
2013-06-24 12:45:28 +08:00
|
|
|
}
|
2012-10-01 17:18:00 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
// FIXME: Many other cases to implement.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-09-10 00:55:27 +08:00
|
|
|
/// Find the context in which we should search for previous declarations when
|
|
|
|
/// looking for declarations to merge.
|
|
|
|
static DeclContext *getPrimaryContextForMerging(DeclContext *DC) {
|
|
|
|
if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
|
|
|
|
return ND->getOriginalNamespace();
|
|
|
|
|
|
|
|
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
|
|
|
|
return RD->getDefinition();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
ASTDeclReader::FindExistingResult::~FindExistingResult() {
|
2012-01-10 01:38:47 +08:00
|
|
|
if (!AddResult || Existing)
|
2011-12-22 09:48:48 +08:00
|
|
|
return;
|
2013-07-13 10:00:19 +08:00
|
|
|
|
|
|
|
DeclContext *DC = New->getDeclContext()->getRedeclContext();
|
|
|
|
if (DC->isTranslationUnit() && Reader.SemaObj) {
|
2012-10-04 02:34:48 +08:00
|
|
|
Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName());
|
2013-09-10 00:55:27 +08:00
|
|
|
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
|
2013-07-13 10:00:19 +08:00
|
|
|
// Add the declaration to its redeclaration context so later merging
|
|
|
|
// lookups will find it.
|
2013-09-10 00:55:27 +08:00
|
|
|
MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true);
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
2012-01-04 06:46:00 +08:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
if (!Name) {
|
|
|
|
// Don't bother trying to find unnamed declarations.
|
|
|
|
FindExistingResult Result(Reader, D, /*Existing=*/0);
|
|
|
|
Result.suppress();
|
|
|
|
return Result;
|
|
|
|
}
|
2013-07-13 10:00:19 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
DeclContext *DC = D->getDeclContext()->getRedeclContext();
|
|
|
|
if (DC->isTranslationUnit() && Reader.SemaObj) {
|
|
|
|
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
|
2013-02-18 23:53:43 +08:00
|
|
|
|
|
|
|
// Temporarily consider the identifier to be up-to-date. We don't want to
|
|
|
|
// cause additional lookups here.
|
|
|
|
class UpToDateIdentifierRAII {
|
|
|
|
IdentifierInfo *II;
|
|
|
|
bool WasOutToDate;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit UpToDateIdentifierRAII(IdentifierInfo *II)
|
|
|
|
: II(II), WasOutToDate(false)
|
|
|
|
{
|
|
|
|
if (II) {
|
|
|
|
WasOutToDate = II->isOutOfDate();
|
|
|
|
if (WasOutToDate)
|
|
|
|
II->setOutOfDate(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~UpToDateIdentifierRAII() {
|
|
|
|
if (WasOutToDate)
|
|
|
|
II->setOutOfDate(true);
|
|
|
|
}
|
|
|
|
} UpToDate(Name.getAsIdentifierInfo());
|
|
|
|
|
2012-01-04 06:46:00 +08:00
|
|
|
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
|
2011-12-22 09:48:48 +08:00
|
|
|
IEnd = IdResolver.end();
|
|
|
|
I != IEnd; ++I) {
|
|
|
|
if (isSameEntity(*I, D))
|
|
|
|
return FindExistingResult(Reader, D, *I);
|
|
|
|
}
|
2013-09-10 00:55:27 +08:00
|
|
|
return FindExistingResult(Reader, D, /*Existing=*/0);
|
|
|
|
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
|
|
|
|
DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
|
2013-07-13 10:00:19 +08:00
|
|
|
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
|
2012-12-19 08:45:41 +08:00
|
|
|
if (isSameEntity(*I, D))
|
|
|
|
return FindExistingResult(Reader, D, *I);
|
2012-01-10 01:38:47 +08:00
|
|
|
}
|
2013-09-10 00:55:27 +08:00
|
|
|
return FindExistingResult(Reader, D, /*Existing=*/0);
|
2012-01-10 01:38:47 +08:00
|
|
|
}
|
2013-09-10 00:55:27 +08:00
|
|
|
|
|
|
|
return FindExistingResult(Reader);
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
|
|
|
|
2011-02-12 15:50:47 +08:00
|
|
|
void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
|
|
|
|
assert(D && previous);
|
|
|
|
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
TD->RedeclLink.setNext(cast<TagDecl>(previous));
|
2011-02-12 15:50:47 +08:00
|
|
|
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
FD->RedeclLink.setNext(cast<FunctionDecl>(previous));
|
2011-02-12 15:50:47 +08:00
|
|
|
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
VD->RedeclLink.setNext(cast<VarDecl>(previous));
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
} else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous));
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous));
|
2012-01-02 03:51:50 +08:00
|
|
|
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
PD->RedeclLink.setNext(cast<ObjCProtocolDecl>(previous));
|
2012-01-07 17:11:48 +08:00
|
|
|
} else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
|
2012-05-29 03:38:42 +08:00
|
|
|
ND->RedeclLink.setNext(cast<NamespaceDecl>(previous));
|
2011-02-12 15:50:47 +08:00
|
|
|
} else {
|
|
|
|
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
|
2012-05-29 03:38:42 +08:00
|
|
|
TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(previous));
|
2011-02-12 15:50:47 +08:00
|
|
|
}
|
2013-08-02 09:09:12 +08:00
|
|
|
|
|
|
|
// If the declaration was visible in one module, a redeclaration of it in
|
|
|
|
// another module remains visible even if it wouldn't be visible by itself.
|
|
|
|
//
|
|
|
|
// FIXME: In this case, the declaration should only be visible if a module
|
|
|
|
// that makes it visible has been imported.
|
|
|
|
D->IdentifierNamespace |=
|
|
|
|
previous->IdentifierNamespace &
|
|
|
|
(Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
|
2011-02-12 15:50:47 +08:00
|
|
|
}
|
|
|
|
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
|
|
|
|
assert(D && Latest);
|
|
|
|
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
|
|
|
TD->RedeclLink
|
|
|
|
= Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
|
|
|
|
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
FD->RedeclLink
|
|
|
|
= Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
|
|
|
|
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
VD->RedeclLink
|
|
|
|
= Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest));
|
|
|
|
} else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
|
|
|
|
TD->RedeclLink
|
|
|
|
= Redeclarable<TypedefNameDecl>::LatestDeclLink(
|
|
|
|
cast<TypedefNameDecl>(Latest));
|
|
|
|
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
|
|
|
ID->RedeclLink
|
|
|
|
= Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(
|
|
|
|
cast<ObjCInterfaceDecl>(Latest));
|
2012-01-02 03:51:50 +08:00
|
|
|
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
|
|
|
|
PD->RedeclLink
|
|
|
|
= Redeclarable<ObjCProtocolDecl>::LatestDeclLink(
|
|
|
|
cast<ObjCProtocolDecl>(Latest));
|
2012-01-07 17:11:48 +08:00
|
|
|
} else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
|
|
|
|
ND->RedeclLink
|
|
|
|
= Redeclarable<NamespaceDecl>::LatestDeclLink(
|
|
|
|
cast<NamespaceDecl>(Latest));
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
} else {
|
|
|
|
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
|
2012-01-14 23:13:49 +08:00
|
|
|
TD->RedeclLink
|
|
|
|
= Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
|
|
|
|
cast<RedeclarableTemplateDecl>(Latest));
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-23 05:40:42 +08:00
|
|
|
ASTReader::MergedDeclsMap::iterator
|
|
|
|
ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) {
|
|
|
|
// If we don't have any stored merged declarations, just look in the
|
|
|
|
// merged declarations set.
|
|
|
|
StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID);
|
|
|
|
if (StoredPos == StoredMergedDecls.end())
|
|
|
|
return MergedDecls.find(Canon);
|
|
|
|
|
|
|
|
// Append the stored merged declarations to the merged declarations set.
|
|
|
|
MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
|
|
|
|
if (Pos == MergedDecls.end())
|
|
|
|
Pos = MergedDecls.insert(std::make_pair(Canon,
|
|
|
|
SmallVector<DeclID, 2>())).first;
|
|
|
|
Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
|
|
|
|
StoredMergedDecls.erase(StoredPos);
|
|
|
|
|
|
|
|
// Sort and uniquify the set of merged declarations.
|
|
|
|
llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
|
|
|
|
Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
|
|
|
|
Pos->second.end());
|
|
|
|
return Pos;
|
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
/// \brief Read the declaration at the given offset from the AST file.
|
2011-08-03 23:48:04 +08:00
|
|
|
Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
2011-08-12 08:15:20 +08:00
|
|
|
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
|
2011-10-28 02:47:35 +08:00
|
|
|
unsigned RawLocation = 0;
|
|
|
|
RecordLocation Loc = DeclCursorForID(ID, RawLocation);
|
2010-10-05 23:59:54 +08:00
|
|
|
llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
|
2009-04-27 13:27:42 +08:00
|
|
|
// Keep track of where we are in the stream, then jump back there
|
|
|
|
// after reading this declaration.
|
2009-04-27 13:58:23 +08:00
|
|
|
SavedStreamPosition SavedPosition(DeclsCursor);
|
2009-04-27 13:27:42 +08:00
|
|
|
|
2010-06-29 06:28:35 +08:00
|
|
|
ReadingKindTracker ReadingKind(Read_Decl, *this);
|
|
|
|
|
2009-07-07 02:54:52 +08:00
|
|
|
// Note that we are loading a declaration record.
|
2010-07-30 18:03:16 +08:00
|
|
|
Deserializing ADecl(this);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-05 23:59:54 +08:00
|
|
|
DeclsCursor.JumpToBit(Loc.Offset);
|
2009-04-27 13:27:42 +08:00
|
|
|
RecordData Record;
|
2009-04-27 13:58:23 +08:00
|
|
|
unsigned Code = DeclsCursor.ReadCode();
|
2009-04-27 13:27:42 +08:00
|
|
|
unsigned Idx = 0;
|
2012-09-18 13:34:55 +08:00
|
|
|
ASTDeclReader Reader(*this, *Loc.F, ID, RawLocation, Record,Idx);
|
2009-04-27 13:27:42 +08:00
|
|
|
|
2009-04-27 13:58:23 +08:00
|
|
|
Decl *D = 0;
|
2013-01-20 10:38:54 +08:00
|
|
|
switch ((DeclCode)DeclsCursor.readRecord(Code, Record)) {
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CONTEXT_LEXICAL:
|
|
|
|
case DECL_CONTEXT_VISIBLE:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord");
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_TYPEDEF:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = TypedefDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2011-04-15 22:24:37 +08:00
|
|
|
case DECL_TYPEALIAS:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = TypeAliasDecl::CreateDeserialized(Context, ID);
|
2011-04-15 22:24:37 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_ENUM:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = EnumDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_RECORD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = RecordDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_ENUM_CONSTANT:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = EnumConstantDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_FUNCTION:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = FunctionDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_LINKAGE_SPEC:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = LinkageSpecDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2011-02-17 15:39:24 +08:00
|
|
|
case DECL_LABEL:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = LabelDecl::CreateDeserialized(Context, ID);
|
2011-02-17 15:39:24 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_NAMESPACE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = NamespaceDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_NAMESPACE_ALIAS:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = NamespaceAliasDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_USING:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = UsingDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_USING_SHADOW:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = UsingShadowDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_USING_DIRECTIVE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = UsingDirectiveDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_UNRESOLVED_USING_VALUE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_UNRESOLVED_USING_TYPENAME:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CXX_RECORD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = CXXRecordDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CXX_METHOD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = CXXMethodDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CXX_CONSTRUCTOR:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = CXXConstructorDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CXX_DESTRUCTOR:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = CXXDestructorDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CXX_CONVERSION:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = CXXConversionDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_ACCESS_SPEC:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = AccessSpecDecl::CreateDeserialized(Context, ID);
|
2010-06-05 13:09:32 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_FRIEND:
|
2013-01-31 17:54:08 +08:00
|
|
|
D = FriendDecl::CreateDeserialized(Context, ID, Record[Idx++]);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_FRIEND_TEMPLATE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = FriendTemplateDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CLASS_TEMPLATE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ClassTemplateDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CLASS_TEMPLATE_SPECIALIZATION:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2013-08-06 09:03:05 +08:00
|
|
|
case DECL_VAR_TEMPLATE:
|
|
|
|
D = VarTemplateDecl::CreateDeserialized(Context, ID);
|
|
|
|
break;
|
|
|
|
case DECL_VAR_TEMPLATE_SPECIALIZATION:
|
|
|
|
D = VarTemplateSpecializationDecl::CreateDeserialized(Context, ID);
|
|
|
|
break;
|
|
|
|
case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION:
|
|
|
|
D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
|
|
|
|
break;
|
2011-08-14 11:52:19 +08:00
|
|
|
case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
|
2011-08-14 11:52:19 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_FUNCTION_TEMPLATE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_TEMPLATE_TYPE_PARM:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = TemplateTypeParmDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_NON_TYPE_TEMPLATE_PARM:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2011-01-20 04:10:05 +08:00
|
|
|
case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, Record[Idx++]);
|
2011-01-20 04:10:05 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_TEMPLATE_TEMPLATE_PARM:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2012-09-07 10:06:42 +08:00
|
|
|
case DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK:
|
|
|
|
D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID,
|
|
|
|
Record[Idx++]);
|
|
|
|
break;
|
2011-05-06 05:57:07 +08:00
|
|
|
case DECL_TYPE_ALIAS_TEMPLATE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID);
|
2011-05-06 05:57:07 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_STATIC_ASSERT:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = StaticAssertDecl::CreateDeserialized(Context, ID);
|
2010-05-08 05:43:38 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_METHOD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCMethodDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_INTERFACE:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCInterfaceDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_IVAR:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCIvarDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_PROTOCOL:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCProtocolDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_AT_DEFS_FIELD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_CATEGORY:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCCategoryDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_CATEGORY_IMPL:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_IMPLEMENTATION:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCImplementationDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_COMPATIBLE_ALIAS:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_PROPERTY:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCPropertyDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_OBJC_PROPERTY_IMPL:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_FIELD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = FieldDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-11-21 14:08:52 +08:00
|
|
|
case DECL_INDIRECTFIELD:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = IndirectFieldDecl::CreateDeserialized(Context, ID);
|
2010-11-21 14:08:52 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_VAR:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = VarDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_IMPLICIT_PARAM:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ImplicitParamDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_PARM_VAR:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ParmVarDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_FILE_SCOPE_ASM:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = FileScopeAsmDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2010-08-19 07:57:32 +08:00
|
|
|
case DECL_BLOCK:
|
2012-01-06 05:55:30 +08:00
|
|
|
D = BlockDecl::CreateDeserialized(Context, ID);
|
2009-04-27 13:27:42 +08:00
|
|
|
break;
|
2013-04-16 15:28:30 +08:00
|
|
|
case DECL_MS_PROPERTY:
|
|
|
|
D = MSPropertyDecl::CreateDeserialized(Context, ID);
|
|
|
|
break;
|
2013-04-17 03:37:38 +08:00
|
|
|
case DECL_CAPTURED:
|
2013-05-04 03:20:19 +08:00
|
|
|
D = CapturedDecl::CreateDeserialized(Context, ID, Record[Idx++]);
|
2013-04-17 03:37:38 +08:00
|
|
|
break;
|
2010-10-30 06:39:52 +08:00
|
|
|
case DECL_CXX_BASE_SPECIFIERS:
|
|
|
|
Error("attempt to read a C++ base-specifier record as a declaration");
|
|
|
|
return 0;
|
2011-12-03 07:23:56 +08:00
|
|
|
case DECL_IMPORT:
|
|
|
|
// Note: last entry of the ImportDecl record is the number of stored source
|
|
|
|
// locations.
|
2012-01-06 05:55:30 +08:00
|
|
|
D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
|
2011-12-03 07:23:56 +08:00
|
|
|
break;
|
2013-03-22 14:34:35 +08:00
|
|
|
case DECL_OMP_THREADPRIVATE:
|
|
|
|
D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record[Idx++]);
|
|
|
|
break;
|
2013-02-23 01:15:32 +08:00
|
|
|
case DECL_EMPTY:
|
|
|
|
D = EmptyDecl::CreateDeserialized(Context, ID);
|
|
|
|
break;
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
assert(D && "Unknown declaration reading AST file");
|
2009-04-27 14:01:06 +08:00
|
|
|
LoadedDecl(Index, D);
|
2012-02-09 14:02:44 +08:00
|
|
|
// Set the DeclContext before doing any deserialization, to make sure internal
|
|
|
|
// calls to Decl::getASTContext() by Decl's methods will find the
|
|
|
|
// TranslationUnitDecl without crashing.
|
|
|
|
D->setDeclContext(Context.getTranslationUnitDecl());
|
2009-04-27 14:01:06 +08:00
|
|
|
Reader.Visit(D);
|
2009-04-27 13:27:42 +08:00
|
|
|
|
|
|
|
// If this declaration is also a declaration context, get the
|
|
|
|
// offsets for its tables of lexical and visible declarations.
|
|
|
|
if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
|
2013-02-07 11:37:08 +08:00
|
|
|
// FIXME: This should really be
|
|
|
|
// DeclContext *LookupDC = DC->getPrimaryContext();
|
|
|
|
// but that can walk the redeclaration chain, which might not work yet.
|
|
|
|
DeclContext *LookupDC = DC;
|
|
|
|
if (isa<NamespaceDecl>(DC))
|
|
|
|
LookupDC = DC->getPrimaryContext();
|
2009-04-27 13:27:42 +08:00
|
|
|
std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
|
|
|
|
if (Offsets.first || Offsets.second) {
|
2011-08-25 03:03:07 +08:00
|
|
|
if (Offsets.first != 0)
|
|
|
|
DC->setHasExternalLexicalStorage(true);
|
|
|
|
if (Offsets.second != 0)
|
2013-02-07 11:37:08 +08:00
|
|
|
LookupDC->setHasExternalVisibleStorage(true);
|
2011-08-25 03:03:07 +08:00
|
|
|
if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets,
|
|
|
|
Loc.F->DeclContextInfos[DC]))
|
2010-07-27 08:17:23 +08:00
|
|
|
return 0;
|
2011-04-25 00:27:54 +08:00
|
|
|
}
|
2010-08-24 08:50:04 +08:00
|
|
|
|
2011-04-25 00:27:54 +08:00
|
|
|
// Now add the pending visible updates for this decl context, if it has any.
|
|
|
|
DeclContextVisibleUpdatesPending::iterator I =
|
|
|
|
PendingVisibleUpdates.find(ID);
|
|
|
|
if (I != PendingVisibleUpdates.end()) {
|
|
|
|
// There are updates. This means the context has external visible
|
|
|
|
// storage, even if the original stored version didn't.
|
2013-02-07 11:37:08 +08:00
|
|
|
LookupDC->setHasExternalVisibleStorage(true);
|
2011-04-25 00:27:54 +08:00
|
|
|
DeclContextVisibleUpdates &U = I->second;
|
|
|
|
for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
|
|
|
|
UI != UE; ++UI) {
|
2012-04-15 20:36:49 +08:00
|
|
|
DeclContextInfo &Info = UI->second->DeclContextInfos[DC];
|
|
|
|
delete Info.NameLookupTableData;
|
|
|
|
Info.NameLookupTableData = UI->first;
|
2010-08-24 08:50:04 +08:00
|
|
|
}
|
2011-04-25 00:27:54 +08:00
|
|
|
PendingVisibleUpdates.erase(I);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(Idx == Record.size());
|
|
|
|
|
2011-08-12 08:15:20 +08:00
|
|
|
// Load any relevant update records.
|
|
|
|
loadDeclUpdateRecords(ID, D);
|
2011-11-14 15:07:59 +08:00
|
|
|
|
2012-01-27 09:47:08 +08:00
|
|
|
// Load the categories after recursive loading is finished.
|
|
|
|
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
|
|
|
|
if (Class->isThisDeclarationADefinition())
|
|
|
|
loadObjCCategories(ID, Class);
|
2011-09-01 08:58:55 +08:00
|
|
|
|
2011-08-12 08:15:20 +08:00
|
|
|
// If we have deserialized a declaration that has a definition the
|
|
|
|
// AST consumer might need to know about, queue it.
|
|
|
|
// We don't pass it to the consumer immediately because we may be in recursive
|
|
|
|
// loading, and some declarations may still be initializing.
|
2012-10-10 01:21:28 +08:00
|
|
|
if (isConsumerInterestedIn(D, Reader.hasPendingBody()))
|
2012-01-27 09:47:08 +08:00
|
|
|
InterestingDecls.push_back(D);
|
2012-10-02 17:09:43 +08:00
|
|
|
|
2011-08-12 08:15:20 +08:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
|
2010-10-25 01:26:36 +08:00
|
|
|
// The declaration may have been modified by files later in the chain.
|
|
|
|
// If this is the case, read the record containing the updates from each file
|
|
|
|
// and pass it to ASTDeclReader to make the modifications.
|
|
|
|
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
|
|
|
|
if (UpdI != DeclUpdateOffsets.end()) {
|
|
|
|
FileOffsetsTy &UpdateOffsets = UpdI->second;
|
|
|
|
for (FileOffsetsTy::iterator
|
2011-08-12 08:15:20 +08:00
|
|
|
I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) {
|
2011-12-01 07:21:26 +08:00
|
|
|
ModuleFile *F = I->first;
|
2010-10-25 01:26:36 +08:00
|
|
|
uint64_t Offset = I->second;
|
|
|
|
llvm::BitstreamCursor &Cursor = F->DeclsCursor;
|
|
|
|
SavedStreamPosition SavedPosition(Cursor);
|
|
|
|
Cursor.JumpToBit(Offset);
|
|
|
|
RecordData Record;
|
|
|
|
unsigned Code = Cursor.ReadCode();
|
2013-01-20 10:38:54 +08:00
|
|
|
unsigned RecCode = Cursor.readRecord(Code, Record);
|
2010-10-25 01:26:36 +08:00
|
|
|
(void)RecCode;
|
|
|
|
assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
|
2011-08-12 08:15:20 +08:00
|
|
|
|
|
|
|
unsigned Idx = 0;
|
2012-09-18 13:34:55 +08:00
|
|
|
ASTDeclReader Reader(*this, *F, ID, 0, Record, Idx);
|
2011-04-29 16:19:30 +08:00
|
|
|
Reader.UpdateDecl(D, *F, Record);
|
2010-10-25 01:26:36 +08:00
|
|
|
}
|
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
2010-10-25 01:26:36 +08:00
|
|
|
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
namespace {
|
|
|
|
struct CompareLocalRedeclarationsInfoToID {
|
|
|
|
bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) {
|
|
|
|
return X.FirstID < Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) {
|
|
|
|
return X < Y.FirstID;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(const LocalRedeclarationsInfo &X,
|
|
|
|
const LocalRedeclarationsInfo &Y) {
|
|
|
|
return X.FirstID < Y.FirstID;
|
|
|
|
}
|
|
|
|
bool operator()(DeclID X, DeclID Y) {
|
|
|
|
return X < Y;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
/// \brief Module visitor class that finds all of the redeclarations of a
|
|
|
|
///
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
class RedeclChainVisitor {
|
|
|
|
ASTReader &Reader;
|
2011-12-22 09:48:48 +08:00
|
|
|
SmallVectorImpl<DeclID> &SearchDecls;
|
2012-01-16 00:58:34 +08:00
|
|
|
llvm::SmallPtrSet<Decl *, 16> &Deserialized;
|
2011-12-22 09:48:48 +08:00
|
|
|
GlobalDeclID CanonID;
|
2013-01-13 03:30:44 +08:00
|
|
|
SmallVector<Decl *, 4> Chain;
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
|
|
|
|
public:
|
2011-12-22 09:48:48 +08:00
|
|
|
RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
|
2012-01-16 00:58:34 +08:00
|
|
|
llvm::SmallPtrSet<Decl *, 16> &Deserialized,
|
2011-12-22 09:48:48 +08:00
|
|
|
GlobalDeclID CanonID)
|
2012-01-16 00:58:34 +08:00
|
|
|
: Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
|
2012-01-18 02:13:45 +08:00
|
|
|
CanonID(CanonID) {
|
|
|
|
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
|
|
|
|
addToChain(Reader.GetDecl(SearchDecls[I]));
|
|
|
|
}
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
|
|
|
|
static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
|
|
|
|
if (Preorder)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return static_cast<RedeclChainVisitor *>(UserData)->visit(M);
|
|
|
|
}
|
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
void addToChain(Decl *D) {
|
|
|
|
if (!D)
|
|
|
|
return;
|
|
|
|
|
2012-08-22 23:37:55 +08:00
|
|
|
if (Deserialized.erase(D))
|
2012-01-16 00:58:34 +08:00
|
|
|
Chain.push_back(D);
|
|
|
|
}
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
void searchForID(ModuleFile &M, GlobalDeclID GlobalID) {
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
// Map global ID of the first declaration down to the local ID
|
|
|
|
// used in this module file.
|
2011-12-22 09:48:48 +08:00
|
|
|
DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
|
|
|
|
if (!ID)
|
|
|
|
return;
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
|
|
|
|
// Perform a binary search to find the local redeclarations for this
|
|
|
|
// declaration (if any).
|
|
|
|
const LocalRedeclarationsInfo *Result
|
2012-01-16 00:58:34 +08:00
|
|
|
= std::lower_bound(M.RedeclarationsMap,
|
|
|
|
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
|
2011-12-22 09:48:48 +08:00
|
|
|
ID, CompareLocalRedeclarationsInfoToID());
|
2012-01-16 00:58:34 +08:00
|
|
|
if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
|
2011-12-22 09:48:48 +08:00
|
|
|
Result->FirstID != ID) {
|
|
|
|
// If we have a previously-canonical singleton declaration that was
|
|
|
|
// merged into another redeclaration chain, create a trivial chain
|
|
|
|
// for this single declaration so that it will get wired into the
|
|
|
|
// complete redeclaration chain.
|
|
|
|
if (GlobalID != CanonID &&
|
|
|
|
GlobalID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
|
|
|
|
GlobalID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls) {
|
2012-01-16 00:58:34 +08:00
|
|
|
addToChain(Reader.GetDecl(GlobalID));
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-27 09:47:08 +08:00
|
|
|
// Dig out all of the redeclarations.
|
2012-01-16 00:58:34 +08:00
|
|
|
unsigned Offset = Result->Offset;
|
|
|
|
unsigned N = M.RedeclarationChains[Offset];
|
|
|
|
M.RedeclarationChains[Offset++] = 0; // Don't try to deserialize again
|
|
|
|
for (unsigned I = 0; I != N; ++I)
|
|
|
|
addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++]));
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool visit(ModuleFile &M) {
|
|
|
|
// Visit each of the declarations.
|
|
|
|
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
|
|
|
|
searchForID(M, SearchDecls[I]);
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
ArrayRef<Decl *> getChain() const {
|
|
|
|
return Chain;
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
|
2011-12-22 09:48:48 +08:00
|
|
|
Decl *D = GetDecl(ID);
|
|
|
|
Decl *CanonDecl = D->getCanonicalDecl();
|
2011-12-23 05:40:42 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
// Determine the set of declaration IDs we'll be searching for.
|
2013-01-13 03:30:44 +08:00
|
|
|
SmallVector<DeclID, 1> SearchDecls;
|
2011-12-22 09:48:48 +08:00
|
|
|
GlobalDeclID CanonID = 0;
|
|
|
|
if (D == CanonDecl) {
|
|
|
|
SearchDecls.push_back(ID); // Always first.
|
|
|
|
CanonID = ID;
|
|
|
|
}
|
2011-12-23 05:40:42 +08:00
|
|
|
MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID);
|
2011-12-22 09:48:48 +08:00
|
|
|
if (MergedPos != MergedDecls.end())
|
2012-10-01 17:18:00 +08:00
|
|
|
SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
// Build up the list of redeclarations.
|
|
|
|
RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor);
|
|
|
|
|
|
|
|
// Retrieve the chains.
|
2012-01-16 00:58:34 +08:00
|
|
|
ArrayRef<Decl *> Chain = Visitor.getChain();
|
|
|
|
if (Chain.empty())
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
return;
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
// Hook up the chains.
|
2012-01-14 23:55:47 +08:00
|
|
|
Decl *MostRecent = CanonDecl->getMostRecentDecl();
|
2012-01-16 00:58:34 +08:00
|
|
|
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
|
|
|
|
if (Chain[I] == CanonDecl)
|
|
|
|
continue;
|
2013-08-02 09:09:12 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent);
|
|
|
|
MostRecent = Chain[I];
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
}
|
2012-01-16 00:58:34 +08:00
|
|
|
|
|
|
|
ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
|
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
llvm-svn: 146841
2011-12-18 07:38:30 +08:00
|
|
|
}
|
|
|
|
|
2011-09-01 08:58:55 +08:00
|
|
|
namespace {
|
2012-01-27 09:47:08 +08:00
|
|
|
struct CompareObjCCategoriesInfo {
|
|
|
|
bool operator()(const ObjCCategoriesInfo &X, DeclID Y) {
|
|
|
|
return X.DefinitionID < Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(DeclID X, const ObjCCategoriesInfo &Y) {
|
|
|
|
return X < Y.DefinitionID;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(const ObjCCategoriesInfo &X,
|
|
|
|
const ObjCCategoriesInfo &Y) {
|
|
|
|
return X.DefinitionID < Y.DefinitionID;
|
|
|
|
}
|
|
|
|
bool operator()(DeclID X, DeclID Y) {
|
|
|
|
return X < Y;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-09-01 08:58:55 +08:00
|
|
|
/// \brief Given an ObjC interface, goes through the modules and links to the
|
|
|
|
/// interface all the categories for it.
|
2012-01-27 09:47:08 +08:00
|
|
|
class ObjCCategoriesVisitor {
|
2011-09-01 08:58:55 +08:00
|
|
|
ASTReader &Reader;
|
|
|
|
serialization::GlobalDeclID InterfaceID;
|
|
|
|
ObjCInterfaceDecl *Interface;
|
2012-01-27 09:47:08 +08:00
|
|
|
llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized;
|
|
|
|
unsigned PreviousGeneration;
|
|
|
|
ObjCCategoryDecl *Tail;
|
2011-09-01 08:58:55 +08:00
|
|
|
llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap;
|
2012-01-27 09:47:08 +08:00
|
|
|
|
|
|
|
void add(ObjCCategoryDecl *Cat) {
|
|
|
|
// Only process each category once.
|
2012-08-22 23:37:55 +08:00
|
|
|
if (!Deserialized.erase(Cat))
|
2012-01-27 09:47:08 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Check for duplicate categories.
|
|
|
|
if (Cat->getDeclName()) {
|
|
|
|
ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()];
|
|
|
|
if (Existing &&
|
|
|
|
Reader.getOwningModuleFile(Existing)
|
|
|
|
!= Reader.getOwningModuleFile(Cat)) {
|
|
|
|
// FIXME: We should not warn for duplicates in diamond:
|
|
|
|
//
|
|
|
|
// MT //
|
|
|
|
// / \ //
|
|
|
|
// ML MR //
|
|
|
|
// \ / //
|
|
|
|
// MB //
|
|
|
|
//
|
|
|
|
// If there are duplicates in ML/MR, there will be warning when
|
|
|
|
// creating MB *and* when importing MB. We should not warn when
|
|
|
|
// importing.
|
|
|
|
Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
|
|
|
|
<< Interface->getDeclName() << Cat->getDeclName();
|
|
|
|
Reader.Diag(Existing->getLocation(), diag::note_previous_definition);
|
|
|
|
} else if (!Existing) {
|
|
|
|
// Record this category.
|
|
|
|
Existing = Cat;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add this category to the end of the chain.
|
|
|
|
if (Tail)
|
|
|
|
ASTDeclReader::setNextObjCCategory(Tail, Cat);
|
|
|
|
else
|
2013-01-17 07:00:23 +08:00
|
|
|
Interface->setCategoryListRaw(Cat);
|
2012-01-27 09:47:08 +08:00
|
|
|
Tail = Cat;
|
|
|
|
}
|
|
|
|
|
2011-09-01 08:58:55 +08:00
|
|
|
public:
|
2012-01-27 09:47:08 +08:00
|
|
|
ObjCCategoriesVisitor(ASTReader &Reader,
|
|
|
|
serialization::GlobalDeclID InterfaceID,
|
|
|
|
ObjCInterfaceDecl *Interface,
|
|
|
|
llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized,
|
|
|
|
unsigned PreviousGeneration)
|
2011-09-01 08:58:55 +08:00
|
|
|
: Reader(Reader), InterfaceID(InterfaceID), Interface(Interface),
|
2012-01-27 09:47:08 +08:00
|
|
|
Deserialized(Deserialized), PreviousGeneration(PreviousGeneration),
|
|
|
|
Tail(0)
|
|
|
|
{
|
|
|
|
// Populate the name -> category map with the set of known categories.
|
2013-01-17 07:00:23 +08:00
|
|
|
for (ObjCInterfaceDecl::known_categories_iterator
|
|
|
|
Cat = Interface->known_categories_begin(),
|
|
|
|
CatEnd = Interface->known_categories_end();
|
|
|
|
Cat != CatEnd; ++Cat) {
|
2012-01-27 09:47:08 +08:00
|
|
|
if (Cat->getDeclName())
|
2013-01-17 07:00:23 +08:00
|
|
|
NameCategoryMap[Cat->getDeclName()] = *Cat;
|
2012-01-27 09:47:08 +08:00
|
|
|
|
|
|
|
// Keep track of the tail of the category list.
|
2013-01-17 07:00:23 +08:00
|
|
|
Tail = *Cat;
|
2012-01-27 09:47:08 +08:00
|
|
|
}
|
|
|
|
}
|
2011-09-01 08:58:55 +08:00
|
|
|
|
2011-12-01 07:21:26 +08:00
|
|
|
static bool visit(ModuleFile &M, void *UserData) {
|
2012-01-27 09:47:08 +08:00
|
|
|
return static_cast<ObjCCategoriesVisitor *>(UserData)->visit(M);
|
2011-09-01 08:58:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-01 07:21:26 +08:00
|
|
|
bool visit(ModuleFile &M) {
|
2012-01-27 09:47:08 +08:00
|
|
|
// If we've loaded all of the category information we care about from
|
|
|
|
// this module file, we're done.
|
|
|
|
if (M.Generation <= PreviousGeneration)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Map global ID of the definition down to the local ID used in this
|
|
|
|
// module file. If there is no such mapping, we'll find nothing here
|
|
|
|
// (or in any module it imports).
|
|
|
|
DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID);
|
|
|
|
if (!LocalID)
|
|
|
|
return true;
|
2011-09-01 08:58:55 +08:00
|
|
|
|
2012-01-27 09:47:08 +08:00
|
|
|
// Perform a binary search to find the local redeclarations for this
|
|
|
|
// declaration (if any).
|
|
|
|
const ObjCCategoriesInfo *Result
|
|
|
|
= std::lower_bound(M.ObjCCategoriesMap,
|
|
|
|
M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
|
|
|
|
LocalID, CompareObjCCategoriesInfo());
|
|
|
|
if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap ||
|
|
|
|
Result->DefinitionID != LocalID) {
|
|
|
|
// We didn't find anything. If the class definition is in this module
|
|
|
|
// file, then the module files it depends on cannot have any categories,
|
|
|
|
// so suppress further lookup.
|
|
|
|
return Reader.isDeclIDFromModule(InterfaceID, M);
|
2011-09-01 08:58:55 +08:00
|
|
|
}
|
2012-01-27 09:47:08 +08:00
|
|
|
|
|
|
|
// We found something. Dig out all of the categories.
|
|
|
|
unsigned Offset = Result->Offset;
|
|
|
|
unsigned N = M.ObjCCategories[Offset];
|
|
|
|
M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again
|
|
|
|
for (unsigned I = 0; I != N; ++I)
|
|
|
|
add(cast_or_null<ObjCCategoryDecl>(
|
|
|
|
Reader.GetLocalDecl(M, M.ObjCCategories[Offset++])));
|
|
|
|
return true;
|
2011-09-01 08:58:55 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2012-01-27 09:47:08 +08:00
|
|
|
void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
|
|
|
|
ObjCInterfaceDecl *D,
|
|
|
|
unsigned PreviousGeneration) {
|
|
|
|
ObjCCategoriesVisitor Visitor(*this, ID, D, CategoriesDeserialized,
|
|
|
|
PreviousGeneration);
|
|
|
|
ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor);
|
2011-09-01 08:58:55 +08:00
|
|
|
}
|
2011-08-12 08:15:20 +08:00
|
|
|
|
2011-12-01 07:21:26 +08:00
|
|
|
void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
|
2011-04-29 16:19:30 +08:00
|
|
|
const RecordData &Record) {
|
2010-10-25 01:26:50 +08:00
|
|
|
unsigned Idx = 0;
|
|
|
|
while (Idx < Record.size()) {
|
|
|
|
switch ((DeclUpdateKind)Record[Idx++]) {
|
2010-10-25 01:26:54 +08:00
|
|
|
case UPD_CXX_ADDED_IMPLICIT_MEMBER:
|
2011-12-01 07:21:26 +08:00
|
|
|
cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx));
|
2010-10-25 01:26:54 +08:00
|
|
|
break;
|
2010-10-28 15:38:42 +08:00
|
|
|
|
|
|
|
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
|
|
|
|
// It will be added to the template's specializations set when loaded.
|
2011-12-01 07:21:26 +08:00
|
|
|
(void)Reader.ReadDecl(ModuleFile, Record, Idx);
|
2011-04-25 00:28:13 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
|
2011-08-03 23:48:04 +08:00
|
|
|
NamespaceDecl *Anon
|
2011-12-01 07:21:26 +08:00
|
|
|
= Reader.ReadDeclAs<NamespaceDecl>(ModuleFile, Record, Idx);
|
2012-01-10 02:07:24 +08:00
|
|
|
|
|
|
|
// Each module has its own anonymous namespace, which is disjoint from
|
|
|
|
// any other module's anonymous namespaces, so don't attach the anonymous
|
|
|
|
// namespace at all.
|
|
|
|
if (ModuleFile.Kind != MK_Module) {
|
|
|
|
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D))
|
|
|
|
TU->setAnonymousNamespace(Anon);
|
|
|
|
else
|
|
|
|
cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon);
|
|
|
|
}
|
2011-04-25 00:28:13 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-04-29 16:19:30 +08:00
|
|
|
|
|
|
|
case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
|
|
|
|
cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation(
|
2011-12-01 07:21:26 +08:00
|
|
|
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
2011-04-29 16:19:30 +08:00
|
|
|
break;
|
2013-05-11 13:45:24 +08:00
|
|
|
|
|
|
|
case UPD_CXX_DEDUCED_RETURN_TYPE: {
|
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(D);
|
|
|
|
Reader.Context.adjustDeducedFunctionResultType(
|
|
|
|
FD, Reader.readType(ModuleFile, Record, Idx));
|
|
|
|
break;
|
|
|
|
}
|
2013-09-05 08:02:25 +08:00
|
|
|
|
|
|
|
case UPD_DECL_MARKED_USED: {
|
2013-09-06 04:13:32 +08:00
|
|
|
// FIXME: This doesn't send the right notifications if there are
|
|
|
|
// ASTMutationListeners other than an ASTWriter.
|
|
|
|
D->setIsUsed(true);
|
2013-09-05 08:02:25 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-10-25 01:26:50 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-25 01:26:36 +08:00
|
|
|
}
|