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;
|
2014-08-28 09:33:39 +08:00
|
|
|
unsigned AnonymousDeclNumber;
|
2014-08-30 08:04:23 +08:00
|
|
|
GlobalDeclID NamedDeclForTagDecl;
|
|
|
|
IdentifierInfo *TypedefNameForLinkage;
|
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);
|
|
|
|
}
|
2015-02-27 08:25:58 +08:00
|
|
|
|
|
|
|
void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
|
|
|
|
for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)
|
|
|
|
IDs.push_back(ReadDeclID(Record, Idx));
|
|
|
|
}
|
|
|
|
|
2011-07-22 06:35:25 +08:00
|
|
|
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));
|
|
|
|
}
|
2014-04-19 11:48:30 +08:00
|
|
|
|
2015-02-03 11:32:14 +08:00
|
|
|
void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
|
2010-10-25 01:26:40 +08:00
|
|
|
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
|
|
|
|
const RecordData &R, unsigned &I);
|
2014-04-19 11:48:30 +08:00
|
|
|
void MergeDefinitionData(CXXRecordDecl *D,
|
2015-01-24 09:07:20 +08:00
|
|
|
struct CXXRecordDecl::DefinitionData &&NewDD);
|
2010-10-25 01:26:40 +08:00
|
|
|
|
2014-08-28 09:33:39 +08:00
|
|
|
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
|
|
|
|
DeclContext *DC,
|
|
|
|
unsigned Index);
|
|
|
|
static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC,
|
|
|
|
unsigned Index, NamedDecl *D);
|
|
|
|
|
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.
|
|
|
|
class RedeclarableResult {
|
|
|
|
ASTReader &Reader;
|
|
|
|
GlobalDeclID FirstID;
|
2015-02-06 10:42:59 +08:00
|
|
|
Decl *MergeWith;
|
2011-12-22 09:48:48 +08:00
|
|
|
mutable bool Owning;
|
2013-01-22 00:16:40 +08:00
|
|
|
Decl::Kind DeclKind;
|
2015-02-25 09:11:29 +08:00
|
|
|
|
2015-02-16 06:54:08 +08:00
|
|
|
void operator=(RedeclarableResult &) = delete;
|
2015-02-25 09:11:29 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
public:
|
2013-01-22 00:16:40 +08:00
|
|
|
RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
|
2015-02-06 10:42:59 +08:00
|
|
|
Decl *MergeWith, Decl::Kind DeclKind)
|
|
|
|
: Reader(Reader), FirstID(FirstID), MergeWith(MergeWith),
|
|
|
|
Owning(true), DeclKind(DeclKind) {}
|
2011-12-22 09:48:48 +08:00
|
|
|
|
2015-02-25 09:11:29 +08:00
|
|
|
RedeclarableResult(RedeclarableResult &&Other)
|
2015-02-06 10:42:59 +08:00
|
|
|
: Reader(Other.Reader), FirstID(Other.FirstID),
|
|
|
|
MergeWith(Other.MergeWith), Owning(Other.Owning),
|
|
|
|
DeclKind(Other.DeclKind) {
|
2011-12-22 09:48:48 +08:00
|
|
|
Other.Owning = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
~RedeclarableResult() {
|
2015-03-06 07:24:12 +08:00
|
|
|
if (FirstID && Owning && isRedeclarableDeclKind(DeclKind)) {
|
|
|
|
auto Canon = Reader.GetDecl(FirstID)->getCanonicalDecl();
|
|
|
|
if (Reader.PendingDeclChainsKnown.insert(Canon).second)
|
|
|
|
Reader.PendingDeclChains.push_back(Canon);
|
|
|
|
}
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
2015-02-25 09:11:29 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
/// \brief Retrieve the first ID.
|
|
|
|
GlobalDeclID getFirstID() const { return FirstID; }
|
2015-02-06 10:42:59 +08:00
|
|
|
|
|
|
|
/// \brief Get a known declaration that this should be merged with, if
|
|
|
|
/// any.
|
|
|
|
Decl *getKnownMergeTarget() const { return MergeWith; }
|
2011-12-22 09:48:48 +08:00
|
|
|
};
|
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;
|
2014-08-30 08:04:23 +08:00
|
|
|
|
2014-08-28 09:33:39 +08:00
|
|
|
unsigned AnonymousDeclNumber;
|
2014-08-30 08:04:23 +08:00
|
|
|
IdentifierInfo *TypedefNameForLinkage;
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2015-02-16 06:54:08 +08:00
|
|
|
void operator=(FindExistingResult&) = delete;
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
public:
|
|
|
|
FindExistingResult(ASTReader &Reader)
|
2014-08-28 09:33:39 +08:00
|
|
|
: Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false),
|
2014-08-30 08:04:23 +08:00
|
|
|
AnonymousDeclNumber(0), TypedefNameForLinkage(0) {}
|
2014-08-28 09:33:39 +08:00
|
|
|
|
|
|
|
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing,
|
2014-08-30 08:04:23 +08:00
|
|
|
unsigned AnonymousDeclNumber,
|
|
|
|
IdentifierInfo *TypedefNameForLinkage)
|
2014-08-28 09:33:39 +08:00
|
|
|
: Reader(Reader), New(New), Existing(Existing), AddResult(true),
|
2014-08-30 08:04:23 +08:00
|
|
|
AnonymousDeclNumber(AnonymousDeclNumber),
|
|
|
|
TypedefNameForLinkage(TypedefNameForLinkage) {}
|
2014-05-22 13:54:18 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
FindExistingResult(const FindExistingResult &Other)
|
2014-08-28 09:33:39 +08:00
|
|
|
: Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
|
|
|
|
AddResult(Other.AddResult),
|
2014-08-30 08:04:23 +08:00
|
|
|
AnonymousDeclNumber(Other.AnonymousDeclNumber),
|
|
|
|
TypedefNameForLinkage(Other.TypedefNameForLinkage) {
|
2011-12-22 09:48:48 +08:00
|
|
|
Other.AddResult = false;
|
|
|
|
}
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
~FindExistingResult();
|
2014-08-28 09:33:39 +08:00
|
|
|
|
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; }
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
operator NamedDecl*() const { return Existing; }
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
template<typename T>
|
|
|
|
operator T*() const { return dyn_cast_or_null<T>(Existing); }
|
|
|
|
};
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2015-01-24 09:07:20 +08:00
|
|
|
static DeclContext *getPrimaryContextForMerging(ASTReader &Reader,
|
|
|
|
DeclContext *DC);
|
2011-12-22 09:48:48 +08:00
|
|
|
FindExistingResult findExisting(NamedDecl *D);
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2009-04-27 13:27:42 +08:00
|
|
|
public:
|
2014-08-30 08:04:23 +08:00
|
|
|
ASTDeclReader(ASTReader &Reader, ModuleFile &F, DeclID thisDeclID,
|
|
|
|
unsigned RawLocation, const RecordData &Record, unsigned &Idx)
|
|
|
|
: Reader(Reader), F(F), ThisDeclID(thisDeclID),
|
|
|
|
RawLocation(RawLocation), Record(Record), Idx(Idx),
|
|
|
|
TypeIDForTypeDecl(0), NamedDeclForTagDecl(0),
|
|
|
|
TypedefNameForLinkage(nullptr), HasPendingBody(false) {}
|
2009-04-27 13:27:42 +08:00
|
|
|
|
2015-02-28 13:57:02 +08:00
|
|
|
template <typename DeclT>
|
|
|
|
static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D);
|
|
|
|
static Decl *getMostRecentDeclImpl(...);
|
|
|
|
static Decl *getMostRecentDecl(Decl *D);
|
|
|
|
|
2014-05-13 09:15:00 +08:00
|
|
|
template <typename DeclT>
|
2014-08-01 07:46:44 +08:00
|
|
|
static void attachPreviousDeclImpl(ASTReader &Reader,
|
2015-03-23 11:25:59 +08:00
|
|
|
Redeclarable<DeclT> *D, Decl *Previous,
|
|
|
|
Decl *Canon);
|
2014-08-01 07:46:44 +08:00
|
|
|
static void attachPreviousDeclImpl(ASTReader &Reader, ...);
|
2015-03-23 11:25:59 +08:00
|
|
|
static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous,
|
|
|
|
Decl *Canon);
|
2014-05-13 09:15:00 +08:00
|
|
|
|
|
|
|
template <typename DeclT>
|
|
|
|
static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
|
|
|
|
static void attachLatestDeclImpl(...);
|
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
|
|
|
|
2014-05-20 04:59:20 +08:00
|
|
|
template <typename DeclT>
|
|
|
|
static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D);
|
|
|
|
static void markIncompleteDeclChainImpl(...);
|
|
|
|
|
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);
|
2014-08-26 11:52:16 +08:00
|
|
|
RedeclarableResult 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);
|
2014-04-24 10:25:27 +08:00
|
|
|
DeclID 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);
|
2014-04-24 10:25:27 +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>
|
2014-04-24 10:25:27 +08:00
|
|
|
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl,
|
|
|
|
DeclID TemplatePatternID = 0);
|
2013-09-10 00:55:27 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
|
2014-04-24 10:25:27 +08:00
|
|
|
RedeclarableResult &Redecl,
|
|
|
|
DeclID TemplatePatternID = 0);
|
2013-09-10 00:55:27 +08:00
|
|
|
|
2013-10-07 16:02:11 +08:00
|
|
|
template<typename T>
|
|
|
|
void mergeMergeable(Mergeable<T> *D);
|
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
void mergeTemplatePattern(RedeclarableTemplateDecl *D,
|
|
|
|
RedeclarableTemplateDecl *Existing,
|
|
|
|
DeclID DsID);
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
ObjCTypeParamList *ReadObjCTypeParamList();
|
|
|
|
|
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);
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
|
2009-04-27 13:27:42 +08:00
|
|
|
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);
|
2015-06-18 07:07:50 +08:00
|
|
|
|
|
|
|
/// We've merged the definition \p MergedDef into the existing definition
|
|
|
|
/// \p Def. Ensure that \p Def is made visible whenever \p MergedDef is made
|
|
|
|
/// visible.
|
|
|
|
void mergeDefinitionVisibility(NamedDecl *Def, NamedDecl *MergedDef) {
|
|
|
|
if (Def->isHidden()) {
|
|
|
|
// If MergedDef is visible or becomes visible, make the definition visible.
|
|
|
|
if (!MergedDef->isHidden())
|
|
|
|
Def->Hidden = false;
|
|
|
|
else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
|
|
|
|
Reader.getContext().mergeDefinitionIntoModule(
|
|
|
|
Def, MergedDef->getImportedOwningModule(),
|
|
|
|
/*NotifyListeners*/ false);
|
|
|
|
Reader.PendingMergedDefinitionsToDeduplicate.insert(Def);
|
|
|
|
} else {
|
|
|
|
auto SubmoduleID = MergedDef->getOwningModuleID();
|
|
|
|
assert(SubmoduleID && "hidden definition in no module");
|
|
|
|
Reader.HiddenNamesMap[Reader.getSubmodule(SubmoduleID)].push_back(Def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2009-04-27 13:27:42 +08:00
|
|
|
|
2015-06-19 06:07:00 +08:00
|
|
|
namespace {
|
|
|
|
/// Iterator over the redeclarations of a declaration that have already
|
|
|
|
/// been merged into the same redeclaration chain.
|
|
|
|
template<typename DeclT>
|
|
|
|
class MergedRedeclIterator {
|
|
|
|
DeclT *Start, *Canonical, *Current;
|
|
|
|
public:
|
|
|
|
MergedRedeclIterator() : Current(nullptr) {}
|
|
|
|
MergedRedeclIterator(DeclT *Start)
|
|
|
|
: Start(Start), Canonical(nullptr), Current(Start) {}
|
|
|
|
|
|
|
|
DeclT *operator*() { return Current; }
|
|
|
|
|
|
|
|
MergedRedeclIterator &operator++() {
|
|
|
|
if (Current->isFirstDecl()) {
|
|
|
|
Canonical = Current;
|
|
|
|
Current = Current->getMostRecentDecl();
|
|
|
|
} else
|
|
|
|
Current = Current->getPreviousDecl();
|
|
|
|
|
|
|
|
// If we started in the merged portion, we'll reach our start position
|
|
|
|
// eventually. Otherwise, we'll never reach it, but the second declaration
|
|
|
|
// we reached was the canonical declaration, so stop when we see that one
|
|
|
|
// again.
|
|
|
|
if (Current == Start || Current == Canonical)
|
|
|
|
Current = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator!=(const MergedRedeclIterator &A,
|
|
|
|
const MergedRedeclIterator &B) {
|
|
|
|
return A.Current != B.Current;
|
|
|
|
}
|
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2015-06-19 06:07:00 +08:00
|
|
|
template<typename DeclT>
|
|
|
|
llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) {
|
|
|
|
return llvm::iterator_range<MergedRedeclIterator<DeclT>>(
|
|
|
|
MergedRedeclIterator<DeclT>(D),
|
|
|
|
MergedRedeclIterator<DeclT>());
|
|
|
|
}
|
|
|
|
|
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)) {
|
2014-04-24 10:25:27 +08:00
|
|
|
// We have a fully initialized TypeDecl. Read its type now.
|
2010-12-11 01:03:06 +08:00
|
|
|
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
|
2014-08-30 08:04:23 +08:00
|
|
|
|
|
|
|
// If this is a tag declaration with a typedef name for linkage, it's safe
|
|
|
|
// to load that typedef now.
|
|
|
|
if (NamedDeclForTagDecl)
|
|
|
|
cast<TagDecl>(D)->NamedDeclOrQualifier =
|
|
|
|
cast<NamedDecl>(Reader.GetDecl(NamedDeclForTagDecl));
|
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: Can we diagnose ODR violations somehow?
|
2012-10-10 01:21:28 +08:00
|
|
|
if (Record[Idx++]) {
|
2015-03-24 14:36:48 +08:00
|
|
|
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
|
|
|
|
CD->NumCtorInitializers = Record[Idx++];
|
|
|
|
if (CD->NumCtorInitializers)
|
|
|
|
CD->CtorInitializers =
|
|
|
|
Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
|
|
|
|
}
|
2012-10-10 01:21:28 +08:00
|
|
|
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) {
|
2013-12-19 10:05:20 +08:00
|
|
|
if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
|
|
|
|
isa<ParmVarDecl>(D)) {
|
2011-03-05 09:35:54 +08:00
|
|
|
// We don't want to deserialize the DeclContext of a template
|
2013-12-19 10:05:20 +08:00
|
|
|
// parameter or of a parameter of a function template immediately. These
|
|
|
|
// entities might be used in the formulation of its DeclContext (for
|
|
|
|
// example, a function parameter can be used in decltype() in trailing
|
|
|
|
// return type of the function). 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-10-24 00:46:34 +08:00
|
|
|
D->Used = 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();
|
2015-05-16 04:05:43 +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);
|
2015-05-16 04:05:43 +08:00
|
|
|
|
|
|
|
if (D->Hidden) {
|
|
|
|
// Module-private declarations are never visible, so there is no work to do.
|
|
|
|
} else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
|
|
|
|
// If local visibility is being tracked, this declaration will become
|
|
|
|
// hidden and visible as the owning module does. Inform Sema that this
|
|
|
|
// declaration might not be visible.
|
|
|
|
D->Hidden = true;
|
|
|
|
} else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
|
|
|
|
if (Owner->NameVisibility != Module::AllVisible) {
|
|
|
|
// The owning module is not visible. Mark this declaration as hidden.
|
|
|
|
D->Hidden = true;
|
|
|
|
|
|
|
|
// Note that this declaration was hidden because its owning module is
|
|
|
|
// not yet visible.
|
|
|
|
Reader.HiddenNamesMap[Owner].push_back(D);
|
2011-12-02 06:20:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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));
|
2015-02-07 11:11:11 +08:00
|
|
|
AnonymousDeclNumber = 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
|
|
|
}
|
|
|
|
|
2014-08-26 11:52:16 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
|
|
|
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);
|
2014-08-26 11:52:16 +08:00
|
|
|
return Redecl;
|
2011-12-19 22:40:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
|
2014-08-26 11:52:16 +08:00
|
|
|
RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
|
|
|
|
mergeRedeclarable(TD, Redecl);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
2011-04-15 22:24:37 +08:00
|
|
|
void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
|
2014-08-26 11:52:16 +08:00
|
|
|
RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
|
|
|
|
if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>(Record, Idx))
|
|
|
|
// Merged when we merge the template.
|
|
|
|
TD->setDescribedAliasTemplate(Template);
|
|
|
|
else
|
|
|
|
mergeRedeclarable(TD, Redecl);
|
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++]);
|
2014-08-28 07:11:59 +08:00
|
|
|
if (!isa<CXXRecordDecl>(TD))
|
|
|
|
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
|
|
|
|
2014-08-30 08:04:23 +08:00
|
|
|
switch (Record[Idx++]) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1: { // ExtInfo
|
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;
|
2014-08-30 08:04:23 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2: // TypedefNameForAnonDecl
|
|
|
|
NamedDeclForTagDecl = ReadDeclID(Record, Idx);
|
|
|
|
TypedefNameForLinkage = Reader.GetIdentifierInfo(F, Record, Idx);
|
|
|
|
break;
|
|
|
|
case 3: // DeclaratorForAnonDecl
|
2014-10-11 06:37:41 +08:00
|
|
|
NamedDeclForTagDecl = ReadDeclID(Record, Idx);
|
2014-08-30 08:04:23 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected tag info kind");
|
|
|
|
}
|
2012-01-04 06:46:00 +08:00
|
|
|
|
2014-04-19 11:48:30 +08:00
|
|
|
if (!isa<CXXRecordDecl>(TD))
|
|
|
|
mergeRedeclarable(TD, Redecl);
|
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::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
|
|
|
|
2013-10-16 06:02:41 +08:00
|
|
|
// If this is a definition subject to the ODR, and we already have a
|
|
|
|
// definition, merge this one into it.
|
|
|
|
if (ED->IsCompleteDefinition &&
|
|
|
|
Reader.getContext().getLangOpts().Modules &&
|
|
|
|
Reader.getContext().getLangOpts().CPlusPlus) {
|
2015-06-19 06:07:00 +08:00
|
|
|
EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
|
|
|
|
if (!OldDef) {
|
|
|
|
// This is the first time we've seen an imported definition. Look for a
|
|
|
|
// local definition before deciding that we are the first definition.
|
|
|
|
for (auto *D : merged_redecls(ED->getCanonicalDecl())) {
|
|
|
|
if (!D->isFromASTFile() && D->isCompleteDefinition()) {
|
|
|
|
OldDef = D;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (OldDef) {
|
2013-10-16 06:02:41 +08:00
|
|
|
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
|
|
|
|
ED->IsCompleteDefinition = false;
|
2015-06-18 07:07:50 +08:00
|
|
|
mergeDefinitionVisibility(OldDef, ED);
|
2013-10-16 06:02:41 +08:00
|
|
|
} else {
|
|
|
|
OldDef = ED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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));
|
2013-10-16 06:02:41 +08:00
|
|
|
mergeMergeable(ECD);
|
2009-04-27 13:27:42 +08:00
|
|
|
}
|
|
|
|
|
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:
|
2014-04-19 11:48:30 +08:00
|
|
|
mergeRedeclarable(FD, Redecl);
|
2010-06-22 17:55:07 +08:00
|
|
|
break;
|
|
|
|
case FunctionDecl::TK_FunctionTemplate:
|
2014-04-19 11:48:30 +08:00
|
|
|
// Merged when we merge the template.
|
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);
|
2014-04-19 11:48:30 +08:00
|
|
|
mergeRedeclarable(FD, Redecl);
|
2010-06-22 17:55:07 +08:00
|
|
|
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,
|
2014-05-22 13:54:18 +08:00
|
|
|
HasTemplateArgumentsAsWritten ? &TemplArgsInfo
|
|
|
|
: nullptr,
|
2011-09-23 04:07:09 +08:00
|
|
|
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;
|
2014-06-26 12:58:53 +08:00
|
|
|
FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs, C);
|
2014-05-22 13:54:18 +08:00
|
|
|
void *InsertPos = nullptr;
|
2013-06-28 12:37:53 +08:00
|
|
|
FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
|
2015-07-02 07:19:58 +08:00
|
|
|
FunctionTemplateSpecializationInfo *ExistingInfo =
|
|
|
|
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");
|
2015-07-02 07:19:58 +08:00
|
|
|
mergeRedeclarable(FD, ExistingInfo->Function, Redecl);
|
2013-06-28 12:37:53 +08:00
|
|
|
}
|
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);
|
2015-07-02 07:19:58 +08:00
|
|
|
// These are not merged; we don't need to merge redeclarations of dependent
|
|
|
|
// template friends.
|
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++]);
|
2014-01-26 00:55:45 +08:00
|
|
|
MD->setReturnType(Reader.readType(F, Record, Idx));
|
|
|
|
MD->setReturnTypeSourceInfo(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
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
|
|
|
|
VisitTypedefNameDecl(D);
|
|
|
|
D->ColonLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() {
|
|
|
|
unsigned numParams = Record[Idx++];
|
|
|
|
if (numParams == 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
SmallVector<ObjCTypeParamDecl *, 4> typeParams;
|
|
|
|
typeParams.reserve(numParams);
|
|
|
|
for (unsigned i = 0; i != numParams; ++i) {
|
|
|
|
auto typeParam = ReadDeclAs<ObjCTypeParamDecl>(Record, Idx);
|
|
|
|
if (!typeParam)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
typeParams.push_back(typeParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation lAngleLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
SourceLocation rAngleLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
|
|
|
return ObjCTypeParamList::create(Reader.getContext(), lAngleLoc,
|
|
|
|
typeParams, rAngleLoc);
|
|
|
|
}
|
|
|
|
|
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);
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
|
|
|
|
ID->TypeParamList = ReadObjCTypeParamList();
|
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);
|
2013-12-04 05:11:30 +08:00
|
|
|
Data.HasDesignatedInitializers = Record[Idx++];
|
2011-12-16 06:34:59 +08:00
|
|
|
|
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.
|
2014-05-22 13:54:18 +08:00
|
|
|
ID->setIvarList(nullptr);
|
|
|
|
|
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.
|
2014-05-22 13:54:18 +08:00
|
|
|
IVD->setNextIvar(nullptr);
|
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);
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
CD->TypeParamList = ReadObjCTypeParamList();
|
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));
|
2015-06-20 02:14:38 +08:00
|
|
|
QualType T = Reader.readType(F, Record, Idx);
|
|
|
|
TypeSourceInfo *TSI = GetTypeSourceInfo(Record, Idx);
|
|
|
|
D->setType(T, TSI);
|
2009-04-27 13:27:42 +08:00
|
|
|
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
|
|
|
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++]);
|
2015-03-24 14:36:48 +08:00
|
|
|
D->NumIvarInitializers = Record[Idx++];
|
|
|
|
if (D->NumIvarInitializers)
|
|
|
|
D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(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++]) {
|
2014-10-11 02:44:34 +08:00
|
|
|
FD->InitStorage.setInt(
|
|
|
|
static_cast<FieldDecl::InitStorageKind>(BitWidthOrInitializer - 1));
|
|
|
|
if (FD->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
|
2014-08-28 12:28:19 +08:00
|
|
|
// Read captured variable length array.
|
2014-10-11 02:44:34 +08:00
|
|
|
FD->InitStorage.setPointer(
|
2014-08-28 12:28:19 +08:00
|
|
|
Reader.readType(F, Record, Idx).getAsOpaquePtr());
|
|
|
|
} else {
|
2014-10-11 02:44:34 +08:00
|
|
|
FD->InitStorage.setPointer(Reader.ReadExpr(F));
|
2014-08-28 12:28:19 +08:00
|
|
|
}
|
2012-06-10 11:12:00 +08:00
|
|
|
}
|
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
|
|
|
}
|
2013-10-07 16:02:11 +08:00
|
|
|
mergeMergeable(FD);
|
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++];
|
2015-05-19 08:57:16 +08:00
|
|
|
if (!isa<ParmVarDecl>(VD)) {
|
|
|
|
VD->NonParmVarDeclBits.ExceptionVar = Record[Idx++];
|
|
|
|
VD->NonParmVarDeclBits.NRVOVariable = Record[Idx++];
|
|
|
|
VD->NonParmVarDeclBits.CXXForRangeDecl = Record[Idx++];
|
|
|
|
VD->NonParmVarDeclBits.ARCPseudoStrong = Record[Idx++];
|
|
|
|
VD->NonParmVarDeclBits.IsConstexpr = Record[Idx++];
|
|
|
|
VD->NonParmVarDeclBits.IsInitCapture = Record[Idx++];
|
|
|
|
VD->NonParmVarDeclBits.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.
|
2014-02-11 14:29:29 +08:00
|
|
|
if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage &&
|
2013-09-20 09:15:31 +08:00
|
|
|
VD->getLexicalDeclContext()->isFunctionOrMethod())
|
|
|
|
VD->setLocalExternDecl();
|
2013-05-26 01:16:20 +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:
|
2014-04-24 10:25:27 +08:00
|
|
|
// Only true variables (not parameters or implicit parameters) can be merged
|
2014-07-11 08:20:06 +08:00
|
|
|
if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam &&
|
|
|
|
!isa<VarTemplateSpecializationDecl>(VD))
|
2014-04-24 10:25:27 +08:00
|
|
|
mergeRedeclarable(VD, Redecl);
|
2013-08-14 11:09:19 +08:00
|
|
|
break;
|
|
|
|
case VarTemplate:
|
2014-04-24 10:25:27 +08:00
|
|
|
// Merged when we merge the template.
|
2013-08-14 11:09:19 +08:00
|
|
|
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);
|
2014-04-24 10:25:27 +08:00
|
|
|
mergeRedeclarable(VD, Redecl);
|
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);
|
2014-05-22 13:54:18 +08:00
|
|
|
Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : nullptr);
|
2011-02-07 18:33:21 +08:00
|
|
|
|
|
|
|
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);
|
2014-05-06 18:08:46 +08:00
|
|
|
unsigned ContextParamPos = Record[Idx++];
|
|
|
|
CD->setNothrow(Record[Idx++] != 0);
|
2013-05-04 03:20:19 +08:00
|
|
|
// Body is set by VisitCapturedStmt.
|
2014-05-06 18:08:46 +08:00
|
|
|
for (unsigned I = 0; I < CD->NumParams; ++I) {
|
|
|
|
if (I != ContextParamPos)
|
|
|
|
CD->setParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
|
|
|
|
else
|
|
|
|
CD->setContextParam(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);
|
2012-01-10 01:30:44 +08:00
|
|
|
|
2015-03-17 10:23:11 +08:00
|
|
|
// Defer loading the anonymous namespace until we've finished merging
|
|
|
|
// this namespace; loading it might load a later declaration of the
|
|
|
|
// same namespace, and we have an invariant that older declarations
|
|
|
|
// get merged before newer ones try to merge.
|
|
|
|
GlobalDeclID AnonNamespace = 0;
|
2012-01-07 17:11:48 +08:00
|
|
|
if (Redecl.getFirstID() == ThisDeclID) {
|
2015-03-17 10:23:11 +08:00
|
|
|
AnonNamespace = ReadDeclID(Record, Idx);
|
2012-01-07 17:11:48 +08:00
|
|
|
} else {
|
|
|
|
// Link this namespace back to the first declaration, which has already
|
|
|
|
// been deserialized.
|
2013-10-17 23:37:26 +08:00
|
|
|
D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl());
|
2012-01-07 17:11:48 +08:00
|
|
|
}
|
2014-07-15 11:37:06 +08:00
|
|
|
|
|
|
|
mergeRedeclarable(D, Redecl);
|
2015-03-17 10:23:11 +08:00
|
|
|
|
|
|
|
if (AnonNamespace) {
|
|
|
|
// 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 = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
|
|
|
|
if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
|
|
|
|
D->setAnonymousNamespace(Anon);
|
|
|
|
}
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
|
2014-09-04 07:11:22 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(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);
|
2014-09-04 07:11:22 +08:00
|
|
|
mergeRedeclarable(D, Redecl);
|
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);
|
2014-10-14 10:00:47 +08:00
|
|
|
mergeMergeable(D);
|
2010-05-08 05:43:38 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:48 +08:00
|
|
|
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
|
2013-10-23 10:17:46 +08:00
|
|
|
RedeclarableResult Redecl = VisitRedeclarable(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);
|
2013-10-23 10:17:46 +08:00
|
|
|
mergeRedeclarable(D, Redecl);
|
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);
|
2014-10-14 10:00:47 +08:00
|
|
|
mergeMergeable(D);
|
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);
|
2014-10-14 10:00:47 +08:00
|
|
|
mergeMergeable(D);
|
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++];
|
2013-12-10 16:25:00 +08:00
|
|
|
Data.HasVariantMembers = 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++];
|
2014-04-18 04:33:01 +08:00
|
|
|
Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
|
2012-11-30 13:11:39 +08:00
|
|
|
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-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) {
|
2014-05-11 00:31:55 +08:00
|
|
|
typedef LambdaCapture Capture;
|
2012-02-15 01:54:36 +08:00
|
|
|
CXXRecordDecl::LambdaDefinitionData &Lambda
|
|
|
|
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
|
2012-02-22 03:11:17 +08:00
|
|
|
Lambda.Dependent = Record[Idx++];
|
2013-10-24 00:10:50 +08:00
|
|
|
Lambda.IsGenericLambda = Record[Idx++];
|
|
|
|
Lambda.CaptureDefault = 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);
|
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:
|
2014-08-28 12:28:19 +08:00
|
|
|
case LCK_VLAType:
|
2014-05-22 13:54:18 +08:00
|
|
|
*ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
|
2013-05-16 14:20:58 +08:00
|
|
|
break;
|
|
|
|
case LCK_ByCopy:
|
2013-09-28 12:02:39 +08:00
|
|
|
case LCK_ByRef:
|
2013-05-16 14:20:58 +08:00
|
|
|
VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
|
|
|
|
SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
*ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
|
|
|
|
break;
|
|
|
|
}
|
2012-02-15 01:54:36 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-25 01:26:27 +08:00
|
|
|
}
|
|
|
|
|
2014-04-19 11:48:30 +08:00
|
|
|
void ASTDeclReader::MergeDefinitionData(
|
2015-01-24 09:07:20 +08:00
|
|
|
CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&MergeDD) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
assert(D->DefinitionData.getNotUpdated() &&
|
|
|
|
"merging class definition into non-definition");
|
|
|
|
auto &DD = *D->DefinitionData.getNotUpdated();
|
2014-04-19 11:48:30 +08:00
|
|
|
|
2015-03-28 05:16:39 +08:00
|
|
|
if (DD.Definition != MergeDD.Definition) {
|
2015-06-20 08:22:34 +08:00
|
|
|
// If the new definition has new special members, let the name lookup
|
|
|
|
// code know that it needs to look in the new definition too.
|
|
|
|
//
|
|
|
|
// FIXME: We only need to do this if the merged definition declares members
|
|
|
|
// that this definition did not declare, or if it defines members that this
|
|
|
|
// definition did not define.
|
2015-03-28 05:16:39 +08:00
|
|
|
Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
|
|
|
|
DD.Definition->setHasExternalVisibleStorage();
|
2015-06-20 08:22:34 +08:00
|
|
|
|
|
|
|
// Track that we merged the definitions.
|
|
|
|
Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
|
|
|
|
DD.Definition));
|
|
|
|
Reader.PendingDefinitions.erase(MergeDD.Definition);
|
|
|
|
MergeDD.Definition->IsCompleteDefinition = false;
|
2015-06-18 07:07:50 +08:00
|
|
|
mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
|
2015-03-28 05:16:39 +08:00
|
|
|
}
|
|
|
|
|
2015-02-03 11:32:14 +08:00
|
|
|
auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);
|
|
|
|
if (PFDI != Reader.PendingFakeDefinitionData.end() &&
|
|
|
|
PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) {
|
2015-01-24 09:07:20 +08:00
|
|
|
// We faked up this definition data because we found a class for which we'd
|
|
|
|
// not yet loaded the definition. Replace it with the real thing now.
|
|
|
|
assert(!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?");
|
2015-02-03 11:32:14 +08:00
|
|
|
PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded;
|
2015-01-24 09:07:20 +08:00
|
|
|
|
|
|
|
// Don't change which declaration is the definition; that is required
|
|
|
|
// to be invariant once we select it.
|
|
|
|
auto *Def = DD.Definition;
|
|
|
|
DD = std::move(MergeDD);
|
|
|
|
DD.Definition = Def;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-19 11:48:30 +08:00
|
|
|
// FIXME: Move this out into a .def file?
|
|
|
|
bool DetectedOdrViolation = false;
|
|
|
|
#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
|
|
|
|
#define MATCH_FIELD(Field) \
|
|
|
|
DetectedOdrViolation |= DD.Field != MergeDD.Field; \
|
|
|
|
OR_FIELD(Field)
|
|
|
|
MATCH_FIELD(UserDeclaredConstructor)
|
|
|
|
MATCH_FIELD(UserDeclaredSpecialMembers)
|
|
|
|
MATCH_FIELD(Aggregate)
|
|
|
|
MATCH_FIELD(PlainOldData)
|
|
|
|
MATCH_FIELD(Empty)
|
|
|
|
MATCH_FIELD(Polymorphic)
|
|
|
|
MATCH_FIELD(Abstract)
|
|
|
|
MATCH_FIELD(IsStandardLayout)
|
|
|
|
MATCH_FIELD(HasNoNonEmptyBases)
|
|
|
|
MATCH_FIELD(HasPrivateFields)
|
|
|
|
MATCH_FIELD(HasProtectedFields)
|
|
|
|
MATCH_FIELD(HasPublicFields)
|
|
|
|
MATCH_FIELD(HasMutableFields)
|
|
|
|
MATCH_FIELD(HasVariantMembers)
|
|
|
|
MATCH_FIELD(HasOnlyCMembers)
|
|
|
|
MATCH_FIELD(HasInClassInitializer)
|
|
|
|
MATCH_FIELD(HasUninitializedReferenceMember)
|
|
|
|
MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
|
|
|
|
MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
|
|
|
|
MATCH_FIELD(NeedOverloadResolutionForDestructor)
|
|
|
|
MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
|
|
|
|
MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
|
|
|
|
MATCH_FIELD(DefaultedDestructorIsDeleted)
|
|
|
|
OR_FIELD(HasTrivialSpecialMembers)
|
|
|
|
OR_FIELD(DeclaredNonTrivialSpecialMembers)
|
|
|
|
MATCH_FIELD(HasIrrelevantDestructor)
|
|
|
|
OR_FIELD(HasConstexprNonCopyMoveConstructor)
|
|
|
|
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
|
|
|
|
OR_FIELD(HasConstexprDefaultConstructor)
|
|
|
|
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
|
|
|
|
// ComputedVisibleConversions is handled below.
|
|
|
|
MATCH_FIELD(UserProvidedDefaultConstructor)
|
|
|
|
OR_FIELD(DeclaredSpecialMembers)
|
|
|
|
MATCH_FIELD(ImplicitCopyConstructorHasConstParam)
|
|
|
|
MATCH_FIELD(ImplicitCopyAssignmentHasConstParam)
|
|
|
|
OR_FIELD(HasDeclaredCopyConstructorWithConstParam)
|
|
|
|
OR_FIELD(HasDeclaredCopyAssignmentWithConstParam)
|
|
|
|
MATCH_FIELD(IsLambda)
|
|
|
|
#undef OR_FIELD
|
|
|
|
#undef MATCH_FIELD
|
|
|
|
|
|
|
|
if (DD.NumBases != MergeDD.NumBases || DD.NumVBases != MergeDD.NumVBases)
|
|
|
|
DetectedOdrViolation = true;
|
|
|
|
// FIXME: Issue a diagnostic if the base classes don't match when we come
|
|
|
|
// to lazily load them.
|
|
|
|
|
|
|
|
// FIXME: Issue a diagnostic if the list of conversion functions doesn't
|
|
|
|
// match when we come to lazily load them.
|
|
|
|
if (MergeDD.ComputedVisibleConversions && !DD.ComputedVisibleConversions) {
|
|
|
|
DD.VisibleConversions = std::move(MergeDD.VisibleConversions);
|
|
|
|
DD.ComputedVisibleConversions = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Issue a diagnostic if FirstFriend doesn't match when we come to
|
|
|
|
// lazily load it.
|
|
|
|
|
|
|
|
if (DD.IsLambda) {
|
|
|
|
// FIXME: ODR-checking for merging lambdas (this happens, for instance,
|
|
|
|
// when they occur within the body of a function template specialization).
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DetectedOdrViolation)
|
|
|
|
Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
|
|
|
|
}
|
|
|
|
|
2015-02-03 11:32:14 +08:00
|
|
|
void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
|
2014-04-19 11:48:30 +08:00
|
|
|
struct CXXRecordDecl::DefinitionData *DD;
|
|
|
|
ASTContext &C = Reader.getContext();
|
|
|
|
|
|
|
|
// Determine whether this is a lambda closure type, so that we can
|
|
|
|
// allocate the appropriate DefinitionData structure.
|
|
|
|
bool IsLambda = Record[Idx++];
|
|
|
|
if (IsLambda)
|
2014-05-22 13:54:18 +08:00
|
|
|
DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false,
|
2014-04-19 11:48:30 +08:00
|
|
|
LCD_None);
|
|
|
|
else
|
|
|
|
DD = new (C) struct CXXRecordDecl::DefinitionData(D);
|
|
|
|
|
|
|
|
ReadCXXDefinitionData(*DD, Record, Idx);
|
|
|
|
|
2015-01-22 09:41:56 +08:00
|
|
|
// We might already have a definition for this record. This can happen either
|
|
|
|
// because we're reading an update record, or because we've already done some
|
|
|
|
// merging. Either way, just merge into it.
|
2015-01-24 09:07:20 +08:00
|
|
|
CXXRecordDecl *Canon = D->getCanonicalDecl();
|
2015-06-20 08:22:34 +08:00
|
|
|
if (Canon->DefinitionData.getNotUpdated()) {
|
2015-01-24 09:07:20 +08:00
|
|
|
MergeDefinitionData(Canon, std::move(*DD));
|
|
|
|
D->DefinitionData = Canon->DefinitionData;
|
2014-04-19 11:48:30 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-20 08:22:34 +08:00
|
|
|
// Mark this declaration as being a definition.
|
|
|
|
D->IsCompleteDefinition = true;
|
|
|
|
D->DefinitionData = DD;
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
|
2015-06-20 08:22:34 +08:00
|
|
|
// If this is not the first declaration or is an update record, we can have
|
|
|
|
// other redeclarations already. Make a note that we need to propagate the
|
|
|
|
// DefinitionData pointer onto them.
|
|
|
|
if (Update || Canon != D) {
|
|
|
|
Canon->DefinitionData = D->DefinitionData;
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
Reader.PendingDefinitions.insert(D);
|
2014-04-19 11:48:30 +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();
|
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:
|
2014-07-11 08:20:06 +08:00
|
|
|
// Merged when we merge the folding set entry in the primary template.
|
|
|
|
if (!isa<ClassTemplateSpecializationDecl>(D))
|
|
|
|
mergeRedeclarable(D, Redecl);
|
2010-06-20 03:29:09 +08:00
|
|
|
break;
|
2014-04-24 10:25:27 +08:00
|
|
|
case CXXRecTemplate: {
|
|
|
|
// Merged when we merge the template.
|
|
|
|
ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
|
|
|
|
D->TemplateOrInstantiation = Template;
|
|
|
|
if (!Template->getTemplatedDecl()) {
|
|
|
|
// We've not actually loaded the ClassTemplateDecl yet, because we're
|
|
|
|
// currently being loaded as its pattern. Rely on it to set up our
|
|
|
|
// TypeForDecl (see VisitClassTemplateDecl).
|
|
|
|
//
|
|
|
|
// Beware: we do not yet know our canonical declaration, and may still
|
|
|
|
// get merged once the surrounding class template has got off the ground.
|
|
|
|
TypeIDForTypeDecl = 0;
|
|
|
|
}
|
2010-06-20 03:29:09 +08:00
|
|
|
break;
|
2014-04-24 10:25:27 +08:00
|
|
|
}
|
2010-06-20 03:29:09 +08:00
|
|
|
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;
|
2014-04-19 11:48:30 +08:00
|
|
|
mergeRedeclarable(D, Redecl);
|
2010-06-20 03:29:09 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-10-15 04:14:38 +08:00
|
|
|
|
2014-04-19 11:48:30 +08:00
|
|
|
bool WasDefinition = Record[Idx++];
|
|
|
|
if (WasDefinition)
|
2015-02-03 11:32:14 +08:00
|
|
|
ReadCXXRecordDefinition(D, /*Update*/false);
|
2014-04-19 11:48:30 +08:00
|
|
|
else
|
|
|
|
// Propagate DefinitionData pointer from the canonical declaration.
|
|
|
|
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
|
|
|
|
|
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)
|
2014-07-07 14:38:20 +08:00
|
|
|
// FIXME: This is wrong for the ARM ABI, where some other module may have
|
|
|
|
// made this function no longer be a key function. We need an update
|
|
|
|
// record or similar for that case.
|
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);
|
2014-08-27 07:29:11 +08:00
|
|
|
|
2010-07-05 05:44:35 +08:00
|
|
|
unsigned NumOverridenMethods = Record[Idx++];
|
2014-08-27 07:29:11 +08:00
|
|
|
if (D->isCanonicalDecl()) {
|
|
|
|
while (NumOverridenMethods--) {
|
|
|
|
// Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
|
|
|
|
// MD may be initializing.
|
|
|
|
if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx))
|
|
|
|
Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We don't care about which declarations this used to override; we get
|
|
|
|
// the relevant information from the canonical declaration.
|
|
|
|
Idx += NumOverridenMethods;
|
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);
|
2014-03-28 03:22:19 +08:00
|
|
|
|
|
|
|
if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
|
2015-02-27 09:57:00 +08:00
|
|
|
if (D->isCanonicalDecl())
|
2015-03-27 06:22:22 +08:00
|
|
|
D->setInheritedConstructor(CD->getCanonicalDecl());
|
2010-07-02 23:58:43 +08:00
|
|
|
D->IsExplicitSpecified = 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
|
|
|
|
2015-03-10 09:41:22 +08:00
|
|
|
if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx)) {
|
|
|
|
auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
|
|
|
|
// FIXME: Check consistency if we have an old and new operator delete.
|
|
|
|
if (!Canon->OperatorDelete)
|
|
|
|
Canon->OperatorDelete = OperatorDelete;
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
2010-06-20 03:29:09 +08:00
|
|
|
VisitNamedDecl(D);
|
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
DeclID PatternID = ReadDeclID(Record, Idx);
|
|
|
|
NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
|
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
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
return PatternID;
|
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
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
DeclID PatternID = VisitTemplateDecl(D);
|
2010-09-09 03:31:22 +08:00
|
|
|
D->IdentifierNamespace = Record[Idx++];
|
2012-10-01 17:18:00 +08:00
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
mergeRedeclarable(D, Redecl, PatternID);
|
2012-10-01 17:18:00 +08:00
|
|
|
|
2013-10-14 07:50:45 +08:00
|
|
|
// If we merged the template with a prior declaration chain, merge the common
|
|
|
|
// pointer.
|
|
|
|
// FIXME: Actually merge here, don't just overwrite.
|
|
|
|
D->Common = D->getCanonicalDecl()->Common;
|
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
return Redecl;
|
2010-07-30 00:11:51 +08:00
|
|
|
}
|
|
|
|
|
2015-02-27 08:25:58 +08:00
|
|
|
static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
|
|
|
|
SmallVectorImpl<DeclID> &IDs) {
|
|
|
|
assert(!IDs.empty() && "no IDs to add to list");
|
2015-02-28 09:45:19 +08:00
|
|
|
if (Old) {
|
|
|
|
IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
|
|
|
|
std::sort(IDs.begin(), IDs.end());
|
|
|
|
IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
|
|
|
|
}
|
2015-02-27 08:25:58 +08:00
|
|
|
|
2015-02-28 09:45:19 +08:00
|
|
|
auto *Result = new (Context) DeclID[1 + IDs.size()];
|
|
|
|
*Result = IDs.size();
|
|
|
|
std::copy(IDs.begin(), IDs.end(), Result + 1);
|
2015-02-27 08:25:58 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
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.
|
2015-02-27 08:25:58 +08:00
|
|
|
SmallVector<serialization::DeclID, 32> SpecIDs;
|
|
|
|
ReadDeclIDList(SpecIDs);
|
|
|
|
|
|
|
|
if (!SpecIDs.empty()) {
|
|
|
|
auto *CommonPtr = D->getCommonPtr();
|
|
|
|
CommonPtr->LazySpecializations = newDeclIDList(
|
|
|
|
Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
|
2010-10-28 06:21:36 +08:00
|
|
|
}
|
2010-06-20 03:29:09 +08:00
|
|
|
}
|
2014-04-24 10:25:27 +08:00
|
|
|
|
|
|
|
if (D->getTemplatedDecl()->TemplateOrInstantiation) {
|
|
|
|
// We were loaded before our templated declaration was. We've not set up
|
|
|
|
// its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct
|
|
|
|
// it now.
|
|
|
|
Reader.Context.getInjectedClassNameType(
|
2014-05-24 05:31:59 +08:00
|
|
|
D->getTemplatedDecl(), D->getInjectedClassNameSpecialization());
|
2014-04-24 10:25:27 +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.
|
2015-02-27 08:25:58 +08:00
|
|
|
SmallVector<serialization::DeclID, 32> SpecIDs;
|
|
|
|
ReadDeclIDList(SpecIDs);
|
|
|
|
|
|
|
|
if (!SpecIDs.empty()) {
|
|
|
|
auto *CommonPtr = D->getCommonPtr();
|
|
|
|
CommonPtr->LazySpecializations = newDeclIDList(
|
|
|
|
Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
if (auto *DDD = D->DefinitionData.getNotUpdated()) {
|
2015-06-20 08:22:34 +08:00
|
|
|
if (CanonSpec->DefinitionData.getNotUpdated())
|
2015-01-24 09:07:20 +08:00
|
|
|
MergeDefinitionData(CanonSpec, std::move(*DDD));
|
2015-06-20 08:22:34 +08:00
|
|
|
else
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
CanonSpec->DefinitionData = D->DefinitionData;
|
2013-09-10 00:55:27 +08:00
|
|
|
}
|
2014-07-12 02:22:58 +08:00
|
|
|
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.
|
2015-02-27 08:25:58 +08:00
|
|
|
SmallVector<serialization::DeclID, 32> SpecIDs;
|
|
|
|
ReadDeclIDList(SpecIDs);
|
2010-06-22 17:55:07 +08:00
|
|
|
|
2015-02-27 08:25:58 +08:00
|
|
|
if (!SpecIDs.empty()) {
|
|
|
|
auto *CommonPtr = D->getCommonPtr();
|
|
|
|
CommonPtr->LazySpecializations = newDeclIDList(
|
|
|
|
Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
|
2013-06-28 12:37:53 +08:00
|
|
|
}
|
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++]);
|
|
|
|
|
2015-06-10 08:29:03 +08:00
|
|
|
if (Record[Idx++])
|
|
|
|
D->setDefaultArgument(GetTypeSourceInfo(Record, Idx));
|
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++];
|
2015-06-10 08:29:03 +08:00
|
|
|
if (Record[Idx++])
|
|
|
|
D->setDefaultArgument(Reader.ReadExpr(F));
|
2011-01-20 04:10:05 +08:00
|
|
|
}
|
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.
|
|
|
|
D->ParameterPack = Record[Idx++];
|
2015-06-10 08:29:03 +08:00
|
|
|
if (Record[Idx++])
|
|
|
|
D->setDefaultArgument(Reader.getContext(),
|
|
|
|
Reader.ReadTemplateArgumentLoc(F, Record, Idx));
|
2012-09-07 10:06:42 +08:00
|
|
|
}
|
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>
|
2015-02-06 10:42:59 +08:00
|
|
|
ASTDeclReader::RedeclarableResult
|
2011-12-22 09:48:48 +08:00
|
|
|
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
2012-01-16 00:58:34 +08:00
|
|
|
DeclID FirstDeclID = ReadDeclID(Record, Idx);
|
2015-02-06 10:42:59 +08:00
|
|
|
Decl *MergeWith = nullptr;
|
|
|
|
|
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;
|
2015-03-06 07:24:12 +08:00
|
|
|
else if (unsigned N = Record[Idx++]) {
|
|
|
|
// We have some declarations that must be before us in our redeclaration
|
|
|
|
// chain. Read them now, and remember that we ought to merge with one of
|
|
|
|
// them.
|
|
|
|
// FIXME: Provide a known merge target to the second and subsequent such
|
|
|
|
// declaration.
|
|
|
|
for (unsigned I = 0; I != N; ++I)
|
|
|
|
MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
|
2015-02-06 10:42:59 +08:00
|
|
|
}
|
|
|
|
|
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);
|
2015-03-26 07:18:30 +08:00
|
|
|
D->First = FirstDecl->getCanonicalDecl();
|
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.
|
2015-02-06 10:42:59 +08:00
|
|
|
return RedeclarableResult(Reader, FirstDeclID, MergeWith,
|
2013-01-22 00:16:40 +08:00
|
|
|
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>
|
2014-07-15 11:37:06 +08:00
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
|
2014-04-24 10:25:27 +08:00
|
|
|
RedeclarableResult &Redecl,
|
|
|
|
DeclID TemplatePatternID) {
|
2014-07-15 11:37:06 +08:00
|
|
|
T *D = static_cast<T*>(DBase);
|
|
|
|
|
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
|
|
|
|
2015-03-10 10:57:50 +08:00
|
|
|
// If we're not the canonical declaration, we don't need to merge.
|
|
|
|
if (!DBase->isFirstDecl())
|
|
|
|
return;
|
|
|
|
|
2015-02-06 10:42:59 +08:00
|
|
|
if (auto *Existing = Redecl.getKnownMergeTarget())
|
|
|
|
// We already know of an existing declaration we should merge with.
|
|
|
|
mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID);
|
|
|
|
else if (FindExistingResult ExistingRes = findExisting(D))
|
2013-09-10 00:55:27 +08:00
|
|
|
if (T *Existing = ExistingRes)
|
2014-04-24 10:25:27 +08:00
|
|
|
mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief "Cast" to type T, asserting if we don't have an implicit conversion.
|
|
|
|
/// We use this to put code in a template that will only be valid for certain
|
|
|
|
/// instantiations.
|
|
|
|
template<typename T> static T assert_cast(T t) { return t; }
|
|
|
|
template<typename T> static T assert_cast(...) {
|
|
|
|
llvm_unreachable("bad assert_cast");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Merge together the pattern declarations from two template
|
|
|
|
/// declarations.
|
|
|
|
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
|
|
|
|
RedeclarableTemplateDecl *Existing,
|
|
|
|
DeclID DsID) {
|
|
|
|
auto *DPattern = D->getTemplatedDecl();
|
|
|
|
auto *ExistingPattern = Existing->getTemplatedDecl();
|
2014-07-15 11:37:06 +08:00
|
|
|
RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
|
2015-02-06 10:42:59 +08:00
|
|
|
/*MergeWith*/ExistingPattern, DPattern->getKind());
|
2015-01-24 09:07:20 +08:00
|
|
|
|
2014-07-12 02:22:58 +08:00
|
|
|
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
|
|
|
|
// Merge with any existing definition.
|
|
|
|
// FIXME: This is duplicated in several places. Refactor.
|
|
|
|
auto *ExistingClass =
|
|
|
|
cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
|
|
|
|
if (auto *DDD = DClass->DefinitionData.getNotUpdated()) {
|
2015-06-20 08:22:34 +08:00
|
|
|
if (ExistingClass->DefinitionData.getNotUpdated()) {
|
2015-01-24 09:07:20 +08:00
|
|
|
MergeDefinitionData(ExistingClass, std::move(*DDD));
|
2014-07-12 02:22:58 +08:00
|
|
|
} else {
|
|
|
|
ExistingClass->DefinitionData = DClass->DefinitionData;
|
2015-06-20 08:22:34 +08:00
|
|
|
// We may have skipped this before because we thought that DClass
|
|
|
|
// was the canonical declaration.
|
2015-03-12 02:21:02 +08:00
|
|
|
Reader.PendingDefinitions.insert(DClass);
|
2014-07-12 02:22:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
DClass->DefinitionData = ExistingClass->DefinitionData;
|
|
|
|
|
2014-04-24 10:25:27 +08:00
|
|
|
return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern),
|
|
|
|
Result);
|
2014-07-12 02:22:58 +08:00
|
|
|
}
|
2014-04-24 10:25:27 +08:00
|
|
|
if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern))
|
|
|
|
return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern),
|
|
|
|
Result);
|
|
|
|
if (auto *DVar = dyn_cast<VarDecl>(DPattern))
|
|
|
|
return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result);
|
2014-07-29 05:16:37 +08:00
|
|
|
if (auto *DAlias = dyn_cast<TypeAliasDecl>(DPattern))
|
|
|
|
return mergeRedeclarable(DAlias, cast<TypedefNameDecl>(ExistingPattern),
|
|
|
|
Result);
|
2014-04-24 10:25:27 +08:00
|
|
|
llvm_unreachable("merged an unknown kind of redeclarable template");
|
2013-09-10 00:55:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Attempts to merge the given declaration (D) with another declaration
|
|
|
|
/// of the same entity.
|
|
|
|
template<typename T>
|
2014-04-24 10:25:27 +08:00
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
|
|
|
|
RedeclarableResult &Redecl,
|
|
|
|
DeclID TemplatePatternID) {
|
|
|
|
T *D = static_cast<T*>(DBase);
|
2013-09-10 00:55:27 +08:00
|
|
|
T *ExistingCanon = Existing->getCanonicalDecl();
|
2014-04-24 10:25:27 +08:00
|
|
|
T *DCanon = D->getCanonicalDecl();
|
2013-09-10 00:55:27 +08:00
|
|
|
if (ExistingCanon != DCanon) {
|
2015-03-10 10:57:50 +08:00
|
|
|
assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
|
|
|
|
"already merged this declaration");
|
2014-07-15 11:37:06 +08:00
|
|
|
|
2013-09-10 00:55:27 +08:00
|
|
|
// Have our redeclaration link point back at the canonical declaration
|
2014-07-15 11:37:06 +08:00
|
|
|
// of the existing declaration, so that this declaration has the
|
2013-09-10 00:55:27 +08:00
|
|
|
// appropriate canonical declaration.
|
|
|
|
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
|
2015-03-26 07:18:30 +08:00
|
|
|
D->First = ExistingCanon;
|
2013-09-10 00:55:27 +08:00
|
|
|
|
|
|
|
// When we merge a namespace, update its pointer to the first namespace.
|
2015-03-17 10:23:11 +08:00
|
|
|
// We cannot have loaded any redeclarations of this declaration yet, so
|
|
|
|
// there's nothing else that needs to be updated.
|
2014-04-24 10:25:27 +08:00
|
|
|
if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
|
2013-09-10 00:55:27 +08:00
|
|
|
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
|
2014-04-24 10:25:27 +08:00
|
|
|
assert_cast<NamespaceDecl*>(ExistingCanon));
|
|
|
|
|
|
|
|
// When we merge a template, merge its pattern.
|
|
|
|
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
|
|
|
|
mergeTemplatePattern(
|
|
|
|
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
|
|
|
|
TemplatePatternID);
|
2013-09-10 00:55:27 +08:00
|
|
|
|
2015-03-17 10:23:11 +08:00
|
|
|
// If this declaration was the canonical declaration, make a note of that.
|
2014-04-24 10:25:27 +08:00
|
|
|
if (DCanon == D) {
|
2015-03-06 07:24:12 +08:00
|
|
|
Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID());
|
|
|
|
if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
|
|
|
|
Reader.PendingDeclChains.push_back(ExistingCanon);
|
2012-01-04 01:27:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 16:02:11 +08:00
|
|
|
/// \brief Attempts to merge the given declaration (D) with another declaration
|
|
|
|
/// of the same entity, for the case where the entity is not actually
|
|
|
|
/// redeclarable. This happens, for instance, when merging the fields of
|
|
|
|
/// identical class definitions from two different modules.
|
|
|
|
template<typename T>
|
|
|
|
void ASTDeclReader::mergeMergeable(Mergeable<T> *D) {
|
|
|
|
// If modules are not available, there is no reason to perform this merge.
|
|
|
|
if (!Reader.getContext().getLangOpts().Modules)
|
|
|
|
return;
|
|
|
|
|
2013-10-16 06:02:41 +08:00
|
|
|
// ODR-based merging is only performed in C++. In C, identically-named things
|
|
|
|
// in different translation units are not redeclarations (but may still have
|
|
|
|
// compatible types).
|
|
|
|
if (!Reader.getContext().getLangOpts().CPlusPlus)
|
|
|
|
return;
|
|
|
|
|
2013-10-07 16:02:11 +08:00
|
|
|
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
|
|
|
|
if (T *Existing = ExistingRes)
|
|
|
|
Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D),
|
|
|
|
Existing->getCanonicalDecl());
|
|
|
|
}
|
|
|
|
|
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) {
|
2014-05-22 13:54:18 +08:00
|
|
|
Attr *New = nullptr;
|
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) ||
|
2014-01-31 09:06:56 +08:00
|
|
|
isa<ObjCImplDecl>(D) ||
|
2014-11-11 12:05:39 +08:00
|
|
|
isa<ImportDecl>(D) ||
|
|
|
|
isa<OMPThreadPrivateDecl>(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());
|
|
|
|
}
|
|
|
|
|
2014-10-14 10:00:47 +08:00
|
|
|
static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
|
|
|
|
if (auto *NS = X->getAsNamespace())
|
|
|
|
return NS;
|
|
|
|
if (auto *NAS = X->getAsNamespaceAlias())
|
|
|
|
return NAS->getNamespace();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isSameQualifier(const NestedNameSpecifier *X,
|
|
|
|
const NestedNameSpecifier *Y) {
|
|
|
|
if (auto *NSX = getNamespace(X)) {
|
|
|
|
auto *NSY = getNamespace(Y);
|
|
|
|
if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl())
|
|
|
|
return false;
|
|
|
|
} else if (X->getKind() != Y->getKind())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// FIXME: For namespaces and types, we're permitted to check that the entity
|
|
|
|
// is named via the same tokens. We should probably do so.
|
|
|
|
switch (X->getKind()) {
|
|
|
|
case NestedNameSpecifier::Identifier:
|
|
|
|
if (X->getAsIdentifier() != Y->getAsIdentifier())
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case NestedNameSpecifier::Namespace:
|
|
|
|
case NestedNameSpecifier::NamespaceAlias:
|
|
|
|
// We've already checked that we named the same namespace.
|
|
|
|
break;
|
|
|
|
case NestedNameSpecifier::TypeSpec:
|
|
|
|
case NestedNameSpecifier::TypeSpecWithTemplate:
|
|
|
|
if (X->getAsType()->getCanonicalTypeInternal() !=
|
|
|
|
Y->getAsType()->getCanonicalTypeInternal())
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case NestedNameSpecifier::Global:
|
|
|
|
case NestedNameSpecifier::Super:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recurse into earlier portion of NNS, if any.
|
|
|
|
auto *PX = X->getPrefix();
|
|
|
|
auto *PY = Y->getPrefix();
|
|
|
|
if (PX && PY)
|
|
|
|
return isSameQualifier(PX, PY);
|
|
|
|
return !PX && !PY;
|
|
|
|
}
|
|
|
|
|
2013-06-25 06:51:00 +08:00
|
|
|
/// \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!");
|
2014-09-04 07:11:22 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
if (X == Y)
|
|
|
|
return true;
|
2014-09-04 07:11:22 +08:00
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
// 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());
|
2014-09-04 07:11:22 +08:00
|
|
|
|
2012-01-05 00:44:10 +08:00
|
|
|
// Must have the same kind.
|
|
|
|
if (X->getKind() != Y->getKind())
|
|
|
|
return false;
|
2014-09-04 07:11:22 +08:00
|
|
|
|
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.
|
2014-09-04 07:11:22 +08:00
|
|
|
// FIXME: This needs to cope with 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
|
|
|
|
2013-10-07 16:02:11 +08:00
|
|
|
// Fields with the same name and the same type match.
|
|
|
|
if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) {
|
|
|
|
FieldDecl *FDY = cast<FieldDecl>(Y);
|
2013-10-16 06:02:41 +08:00
|
|
|
// FIXME: Also check the bitwidth is odr-equivalent, if any.
|
2013-10-07 16:02:11 +08:00
|
|
|
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
|
|
|
|
}
|
|
|
|
|
2013-10-16 06:02:41 +08:00
|
|
|
// Enumerators with the same name match.
|
|
|
|
if (isa<EnumConstantDecl>(X))
|
|
|
|
// FIXME: Also check the value is odr-equivalent.
|
|
|
|
return true;
|
|
|
|
|
2013-10-23 10:17:46 +08:00
|
|
|
// Using shadow declarations with the same target match.
|
|
|
|
if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) {
|
|
|
|
UsingShadowDecl *USY = cast<UsingShadowDecl>(Y);
|
|
|
|
return USX->getTargetDecl() == USY->getTargetDecl();
|
|
|
|
}
|
|
|
|
|
2014-10-14 10:00:47 +08:00
|
|
|
// Using declarations with the same qualifier match. (We already know that
|
|
|
|
// the name matches.)
|
|
|
|
if (auto *UX = dyn_cast<UsingDecl>(X)) {
|
|
|
|
auto *UY = cast<UsingDecl>(Y);
|
|
|
|
return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
|
|
|
|
UX->hasTypename() == UY->hasTypename() &&
|
|
|
|
UX->isAccessDeclaration() == UY->isAccessDeclaration();
|
|
|
|
}
|
|
|
|
if (auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
|
|
|
|
auto *UY = cast<UnresolvedUsingValueDecl>(Y);
|
|
|
|
return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
|
|
|
|
UX->isAccessDeclaration() == UY->isAccessDeclaration();
|
|
|
|
}
|
|
|
|
if (auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
|
|
|
|
return isSameQualifier(
|
|
|
|
UX->getQualifier(),
|
|
|
|
cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
|
|
|
|
|
2014-09-04 07:11:22 +08:00
|
|
|
// Namespace alias definitions with the same target match.
|
|
|
|
if (auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
|
|
|
|
auto *NAY = cast<NamespaceAliasDecl>(Y);
|
|
|
|
return NAX->getNamespace()->Equals(NAY->getNamespace());
|
|
|
|
}
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
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.
|
2015-01-24 09:07:20 +08:00
|
|
|
DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
|
|
|
|
DeclContext *DC) {
|
2013-09-10 00:55:27 +08:00
|
|
|
if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
|
|
|
|
return ND->getOriginalNamespace();
|
|
|
|
|
2015-01-24 09:07:20 +08:00
|
|
|
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
|
|
|
|
// Try to dig out the definition.
|
|
|
|
auto *DD = RD->DefinitionData.getNotUpdated();
|
|
|
|
if (!DD)
|
|
|
|
DD = RD->getCanonicalDecl()->DefinitionData.getNotUpdated();
|
|
|
|
|
|
|
|
// If there's no definition yet, then DC's definition is added by an update
|
|
|
|
// record, but we've not yet loaded that update record. In this case, we
|
|
|
|
// commit to DC being the canonical definition now, and will fix this when
|
|
|
|
// we load the update record.
|
|
|
|
if (!DD) {
|
|
|
|
DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD);
|
|
|
|
RD->IsCompleteDefinition = true;
|
|
|
|
RD->DefinitionData = DD;
|
|
|
|
RD->getCanonicalDecl()->DefinitionData = DD;
|
|
|
|
|
|
|
|
// Track that we did this horrible thing so that we can fix it later.
|
2015-02-03 11:32:14 +08:00
|
|
|
Reader.PendingFakeDefinitionData.insert(
|
|
|
|
std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake));
|
2015-01-24 09:07:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return DD->Definition;
|
|
|
|
}
|
2013-09-10 00:55:27 +08:00
|
|
|
|
2013-10-16 06:02:41 +08:00
|
|
|
if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
|
2014-05-22 13:54:18 +08:00
|
|
|
return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
|
|
|
|
: nullptr;
|
2013-10-16 06:02:41 +08:00
|
|
|
|
2015-02-05 07:37:59 +08:00
|
|
|
// We can see the TU here only if we have no Sema object. In that case,
|
|
|
|
// there's no TU scope to look in, so using the DC alone is sufficient.
|
|
|
|
if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
|
|
|
|
return TU;
|
|
|
|
|
2014-05-22 13:54:18 +08:00
|
|
|
return nullptr;
|
2013-09-10 00:55:27 +08:00
|
|
|
}
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
ASTDeclReader::FindExistingResult::~FindExistingResult() {
|
2015-01-22 10:21:23 +08:00
|
|
|
// Record that we had a typedef name for linkage whether or not we merge
|
|
|
|
// with that declaration.
|
|
|
|
if (TypedefNameForLinkage) {
|
|
|
|
DeclContext *DC = New->getDeclContext()->getRedeclContext();
|
|
|
|
Reader.ImportedTypedefNamesForLinkage.insert(
|
|
|
|
std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2014-08-30 08:04:23 +08:00
|
|
|
DeclarationName Name = New->getDeclName();
|
2013-07-13 10:00:19 +08:00
|
|
|
DeclContext *DC = New->getDeclContext()->getRedeclContext();
|
2015-02-07 11:11:11 +08:00
|
|
|
if (needsAnonymousDeclarationNumber(New)) {
|
2014-08-28 09:33:39 +08:00
|
|
|
setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
|
|
|
|
AnonymousDeclNumber, New);
|
2015-03-23 11:25:59 +08:00
|
|
|
} else if (DC->isTranslationUnit() && Reader.SemaObj &&
|
|
|
|
!Reader.getContext().getLangOpts().CPlusPlus) {
|
|
|
|
if (Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name))
|
|
|
|
Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()]
|
|
|
|
.push_back(New);
|
2015-01-24 09:07:20 +08:00
|
|
|
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-23 09:45:27 +08:00
|
|
|
/// Find the declaration that should be merged into, given the declaration found
|
|
|
|
/// by name lookup. If we're merging an anonymous declaration within a typedef,
|
|
|
|
/// we need a matching typedef, and we merge with the type inside it.
|
|
|
|
static NamedDecl *getDeclForMerging(NamedDecl *Found,
|
|
|
|
bool IsTypedefNameForLinkage) {
|
|
|
|
if (!IsTypedefNameForLinkage)
|
|
|
|
return Found;
|
|
|
|
|
|
|
|
// If we found a typedef declaration that gives a name to some other
|
|
|
|
// declaration, then we want that inner declaration. Declarations from
|
|
|
|
// AST files are handled via ImportedTypedefNamesForLinkage.
|
2015-03-27 09:37:43 +08:00
|
|
|
if (Found->isFromASTFile())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (auto *TND = dyn_cast<TypedefNameDecl>(Found))
|
|
|
|
return TND->getAnonDeclWithTypedefName();
|
2014-08-23 09:45:27 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-28 09:33:39 +08:00
|
|
|
NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
|
|
|
|
DeclContext *DC,
|
|
|
|
unsigned Index) {
|
|
|
|
// If the lexical context has been merged, look into the now-canonical
|
|
|
|
// definition.
|
|
|
|
if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
|
|
|
|
DC = Merged;
|
|
|
|
|
|
|
|
// If we've seen this before, return the canonical declaration.
|
|
|
|
auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
|
|
|
|
if (Index < Previous.size() && Previous[Index])
|
|
|
|
return Previous[Index];
|
|
|
|
|
|
|
|
// If this is the first time, but we have parsed a declaration of the context,
|
|
|
|
// build the anonymous declaration list from the parsed declaration.
|
|
|
|
if (!cast<Decl>(DC)->isFromASTFile()) {
|
2015-02-07 11:11:11 +08:00
|
|
|
numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) {
|
|
|
|
if (Previous.size() == Number)
|
2014-08-28 09:33:39 +08:00
|
|
|
Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
|
|
|
|
else
|
2015-02-07 11:11:11 +08:00
|
|
|
Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl());
|
|
|
|
});
|
2014-08-28 09:33:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Index < Previous.size() ? Previous[Index] : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader,
|
|
|
|
DeclContext *DC, unsigned Index,
|
|
|
|
NamedDecl *D) {
|
|
|
|
if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
|
|
|
|
DC = Merged;
|
|
|
|
|
|
|
|
auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
|
|
|
|
if (Index >= Previous.size())
|
|
|
|
Previous.resize(Index + 1);
|
|
|
|
if (!Previous[Index])
|
|
|
|
Previous[Index] = D;
|
|
|
|
}
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
2014-08-30 08:04:23 +08:00
|
|
|
DeclarationName Name = TypedefNameForLinkage ? TypedefNameForLinkage
|
|
|
|
: D->getDeclName();
|
2014-08-23 09:45:27 +08:00
|
|
|
|
2014-08-28 09:33:39 +08:00
|
|
|
if (!Name && !needsAnonymousDeclarationNumber(D)) {
|
|
|
|
// Don't bother trying to find unnamed declarations that are in
|
|
|
|
// unmergeable contexts.
|
2014-08-30 08:04:23 +08:00
|
|
|
FindExistingResult Result(Reader, D, /*Existing=*/nullptr,
|
|
|
|
AnonymousDeclNumber, TypedefNameForLinkage);
|
2012-01-04 06:46:00 +08:00
|
|
|
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();
|
2014-08-30 08:04:23 +08:00
|
|
|
if (TypedefNameForLinkage) {
|
2014-08-23 09:45:27 +08:00
|
|
|
auto It = Reader.ImportedTypedefNamesForLinkage.find(
|
2014-08-30 08:04:23 +08:00
|
|
|
std::make_pair(DC, TypedefNameForLinkage));
|
2014-08-23 09:45:27 +08:00
|
|
|
if (It != Reader.ImportedTypedefNamesForLinkage.end())
|
|
|
|
if (isSameEntity(It->second, D))
|
2014-08-30 08:04:23 +08:00
|
|
|
return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber,
|
|
|
|
TypedefNameForLinkage);
|
2014-08-23 09:45:27 +08:00
|
|
|
// Go on to check in other places in case an existing typedef name
|
|
|
|
// was not imported.
|
|
|
|
}
|
2014-08-28 09:33:39 +08:00
|
|
|
|
2015-02-07 11:11:11 +08:00
|
|
|
if (needsAnonymousDeclarationNumber(D)) {
|
2014-08-28 09:33:39 +08:00
|
|
|
// This is an anonymous declaration that we may need to merge. Look it up
|
|
|
|
// in its context by number.
|
|
|
|
if (auto *Existing = getAnonymousDeclForMerging(
|
|
|
|
Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
|
|
|
|
if (isSameEntity(Existing, D))
|
2014-08-30 08:04:23 +08:00
|
|
|
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
|
|
|
|
TypedefNameForLinkage);
|
2015-03-23 11:25:59 +08:00
|
|
|
} else if (DC->isTranslationUnit() && Reader.SemaObj &&
|
|
|
|
!Reader.getContext().getLangOpts().CPlusPlus) {
|
2011-12-22 09:48:48 +08:00
|
|
|
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) {
|
2014-08-30 08:04:23 +08:00
|
|
|
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
|
2014-08-26 07:33:46 +08:00
|
|
|
if (isSameEntity(Existing, D))
|
2014-08-30 08:04:23 +08:00
|
|
|
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
|
|
|
|
TypedefNameForLinkage);
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
2015-01-24 09:07:20 +08:00
|
|
|
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
|
2013-09-10 00:55:27 +08:00
|
|
|
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) {
|
2014-08-30 08:04:23 +08:00
|
|
|
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
|
2014-08-23 09:45:27 +08:00
|
|
|
if (isSameEntity(Existing, D))
|
2014-08-30 08:04:23 +08:00
|
|
|
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
|
|
|
|
TypedefNameForLinkage);
|
2012-01-10 01:38:47 +08:00
|
|
|
}
|
2013-10-18 14:05:18 +08:00
|
|
|
} else {
|
|
|
|
// Not in a mergeable context.
|
|
|
|
return FindExistingResult(Reader);
|
2012-01-10 01:38:47 +08:00
|
|
|
}
|
2013-09-10 00:55:27 +08:00
|
|
|
|
2013-10-18 14:05:18 +08:00
|
|
|
// If this declaration is from a merged context, make a note that we need to
|
|
|
|
// check that the canonical definition of that context contains the decl.
|
2014-04-19 11:48:30 +08:00
|
|
|
//
|
|
|
|
// FIXME: We should do something similar if we merge two definitions of the
|
|
|
|
// same template specialization into the same CXXRecordDecl.
|
2014-08-25 10:10:01 +08:00
|
|
|
auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext());
|
|
|
|
if (MergedDCIt != Reader.MergedDeclContexts.end() &&
|
|
|
|
MergedDCIt->second == D->getDeclContext())
|
2013-10-18 14:05:18 +08:00
|
|
|
Reader.PendingOdrMergeChecks.push_back(D);
|
|
|
|
|
2014-08-28 09:33:39 +08:00
|
|
|
return FindExistingResult(Reader, D, /*Existing=*/nullptr,
|
2014-08-30 08:04:23 +08:00
|
|
|
AnonymousDeclNumber, TypedefNameForLinkage);
|
2011-12-22 09:48:48 +08:00
|
|
|
}
|
|
|
|
|
2015-02-28 13:57:02 +08:00
|
|
|
template<typename DeclT>
|
|
|
|
Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) {
|
|
|
|
return D->RedeclLink.getLatestNotUpdated();
|
|
|
|
}
|
|
|
|
Decl *ASTDeclReader::getMostRecentDeclImpl(...) {
|
|
|
|
llvm_unreachable("getMostRecentDecl on non-redeclarable declaration");
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl *ASTDeclReader::getMostRecentDecl(Decl *D) {
|
|
|
|
assert(D);
|
|
|
|
|
|
|
|
switch (D->getKind()) {
|
|
|
|
#define ABSTRACT_DECL(TYPE)
|
|
|
|
#define DECL(TYPE, BASE) \
|
|
|
|
case Decl::TYPE: \
|
|
|
|
return getMostRecentDeclImpl(cast<TYPE##Decl>(D));
|
|
|
|
#include "clang/AST/DeclNodes.inc"
|
|
|
|
}
|
|
|
|
llvm_unreachable("unknown decl kind");
|
|
|
|
}
|
|
|
|
|
2015-03-11 09:44:51 +08:00
|
|
|
Decl *ASTReader::getMostRecentExistingDecl(Decl *D) {
|
|
|
|
return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl());
|
|
|
|
}
|
|
|
|
|
2014-05-13 09:15:00 +08:00
|
|
|
template<typename DeclT>
|
2014-08-01 07:46:44 +08:00
|
|
|
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
|
|
|
|
Redeclarable<DeclT> *D,
|
2015-03-23 11:25:59 +08:00
|
|
|
Decl *Previous, Decl *Canon) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
D->RedeclLink.setPrevious(cast<DeclT>(Previous));
|
2015-03-26 07:18:30 +08:00
|
|
|
D->First = cast<DeclT>(Previous)->First;
|
2014-05-13 09:15:00 +08:00
|
|
|
}
|
2014-08-01 07:52:38 +08:00
|
|
|
namespace clang {
|
2014-08-01 07:46:44 +08:00
|
|
|
template<>
|
|
|
|
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
|
|
|
|
Redeclarable<FunctionDecl> *D,
|
2015-03-23 11:25:59 +08:00
|
|
|
Decl *Previous, Decl *Canon) {
|
2014-08-01 07:46:44 +08:00
|
|
|
FunctionDecl *FD = static_cast<FunctionDecl*>(D);
|
|
|
|
FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
|
|
|
|
|
|
|
|
FD->RedeclLink.setPrevious(PrevFD);
|
2015-03-26 07:18:30 +08:00
|
|
|
FD->First = PrevFD->First;
|
2014-08-01 07:46:44 +08:00
|
|
|
|
|
|
|
// If the previous declaration is an inline function declaration, then this
|
|
|
|
// declaration is too.
|
|
|
|
if (PrevFD->IsInline != FD->IsInline) {
|
|
|
|
// FIXME: [dcl.fct.spec]p4:
|
|
|
|
// If a function with external linkage is declared inline in one
|
|
|
|
// translation unit, it shall be declared inline in all translation
|
|
|
|
// units in which it appears.
|
|
|
|
//
|
|
|
|
// Be careful of this case:
|
|
|
|
//
|
|
|
|
// module A:
|
|
|
|
// template<typename T> struct X { void f(); };
|
|
|
|
// template<typename T> inline void X<T>::f() {}
|
|
|
|
//
|
|
|
|
// module B instantiates the declaration of X<int>::f
|
|
|
|
// module C instantiates the definition of X<int>::f
|
|
|
|
//
|
|
|
|
// If module B and C are merged, we do not have a violation of this rule.
|
|
|
|
FD->IsInline = true;
|
|
|
|
}
|
|
|
|
|
2015-03-23 11:25:59 +08:00
|
|
|
// If we need to propagate an exception specification along the redecl
|
|
|
|
// chain, make a note of that so that we can do so later.
|
2014-08-01 07:46:44 +08:00
|
|
|
auto *FPT = FD->getType()->getAs<FunctionProtoType>();
|
|
|
|
auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
|
2015-03-10 10:00:53 +08:00
|
|
|
if (FPT && PrevFPT) {
|
2015-03-23 11:25:59 +08:00
|
|
|
bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
|
|
|
|
bool WasUnresolved =
|
|
|
|
isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
|
|
|
|
if (IsUnresolved != WasUnresolved)
|
|
|
|
Reader.PendingExceptionSpecUpdates.insert(
|
|
|
|
std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
|
2014-08-01 07:46:44 +08:00
|
|
|
}
|
|
|
|
}
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2014-08-01 07:46:44 +08:00
|
|
|
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
|
2014-05-13 09:15:00 +08:00
|
|
|
llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
|
|
|
|
}
|
|
|
|
|
2015-06-10 09:47:58 +08:00
|
|
|
/// Inherit the default template argument from \p From to \p To. Returns
|
|
|
|
/// \c false if there is no default template for \p From.
|
|
|
|
template <typename ParmDecl>
|
|
|
|
static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From,
|
|
|
|
Decl *ToD) {
|
|
|
|
auto *To = cast<ParmDecl>(ToD);
|
|
|
|
if (!From->hasDefaultArgument())
|
|
|
|
return false;
|
2015-06-11 04:30:23 +08:00
|
|
|
To->setInheritedDefaultArgument(Context, From);
|
2015-06-10 09:47:58 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void inheritDefaultTemplateArguments(ASTContext &Context,
|
|
|
|
TemplateDecl *From,
|
|
|
|
TemplateDecl *To) {
|
|
|
|
auto *FromTP = From->getTemplateParameters();
|
|
|
|
auto *ToTP = To->getTemplateParameters();
|
|
|
|
assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");
|
|
|
|
|
|
|
|
for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
|
|
|
|
NamedDecl *FromParam = FromTP->getParam(N - I - 1);
|
|
|
|
NamedDecl *ToParam = ToTP->getParam(N - I - 1);
|
|
|
|
|
|
|
|
if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) {
|
2015-06-18 06:13:23 +08:00
|
|
|
if (!inheritDefaultTemplateArgument(Context, FTTP, ToParam))
|
2015-06-10 09:47:58 +08:00
|
|
|
break;
|
|
|
|
} else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
|
2015-06-18 06:13:23 +08:00
|
|
|
if (!inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
|
2015-06-10 09:47:58 +08:00
|
|
|
break;
|
|
|
|
} else {
|
2015-06-18 06:13:23 +08:00
|
|
|
if (!inheritDefaultTemplateArgument(
|
2015-06-10 09:47:58 +08:00
|
|
|
Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 07:46:44 +08:00
|
|
|
void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
|
2015-03-23 11:25:59 +08:00
|
|
|
Decl *Previous, Decl *Canon) {
|
2014-05-13 09:15:00 +08:00
|
|
|
assert(D && Previous);
|
|
|
|
|
|
|
|
switch (D->getKind()) {
|
|
|
|
#define ABSTRACT_DECL(TYPE)
|
2015-03-23 11:25:59 +08:00
|
|
|
#define DECL(TYPE, BASE) \
|
|
|
|
case Decl::TYPE: \
|
|
|
|
attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \
|
2014-05-13 09:15:00 +08:00
|
|
|
break;
|
|
|
|
#include "clang/AST/DeclNodes.inc"
|
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 |=
|
2014-05-13 09:15:00 +08:00
|
|
|
Previous->IdentifierNamespace &
|
2013-08-02 09:09:12 +08:00
|
|
|
(Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
|
2014-05-29 11:15:31 +08:00
|
|
|
|
2014-06-17 04:26:19 +08:00
|
|
|
// If the previous declaration is marked as used, then this declaration should
|
|
|
|
// be too.
|
|
|
|
if (Previous->Used)
|
|
|
|
D->Used = true;
|
2015-06-10 09:47:58 +08:00
|
|
|
|
|
|
|
// If the declaration declares a template, it may inherit default arguments
|
|
|
|
// from the previous declaration.
|
|
|
|
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
|
|
|
|
inheritDefaultTemplateArguments(Reader.getContext(),
|
|
|
|
cast<TemplateDecl>(Previous), TD);
|
2011-02-12 15:50:47 +08:00
|
|
|
}
|
|
|
|
|
2014-05-13 09:15:00 +08:00
|
|
|
template<typename DeclT>
|
|
|
|
void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
D->RedeclLink.setLatest(cast<DeclT>(Latest));
|
2014-05-13 09:15:00 +08:00
|
|
|
}
|
|
|
|
void ASTDeclReader::attachLatestDeclImpl(...) {
|
|
|
|
llvm_unreachable("attachLatestDecl on non-redeclarable declaration");
|
|
|
|
}
|
|
|
|
|
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);
|
2014-05-13 09:15:00 +08:00
|
|
|
|
|
|
|
switch (D->getKind()) {
|
|
|
|
#define ABSTRACT_DECL(TYPE)
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
#define DECL(TYPE, BASE) \
|
|
|
|
case Decl::TYPE: \
|
2014-05-13 09:15:00 +08:00
|
|
|
attachLatestDeclImpl(cast<TYPE##Decl>(D), Latest); \
|
|
|
|
break;
|
|
|
|
#include "clang/AST/DeclNodes.inc"
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-20 04:59:20 +08:00
|
|
|
template<typename DeclT>
|
|
|
|
void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) {
|
|
|
|
D->RedeclLink.markIncomplete();
|
|
|
|
}
|
|
|
|
void ASTDeclReader::markIncompleteDeclChainImpl(...) {
|
|
|
|
llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTReader::markIncompleteDeclChain(Decl *D) {
|
|
|
|
switch (D->getKind()) {
|
|
|
|
#define ABSTRACT_DECL(TYPE)
|
|
|
|
#define DECL(TYPE, BASE) \
|
|
|
|
case Decl::TYPE: \
|
|
|
|
ASTDeclReader::markIncompleteDeclChainImpl(cast<TYPE##Decl>(D)); \
|
|
|
|
break;
|
|
|
|
#include "clang/AST/DeclNodes.inc"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2014-05-22 13:54:18 +08:00
|
|
|
Decl *D = nullptr;
|
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");
|
2014-05-22 13:54:18 +08:00
|
|
|
return nullptr;
|
2015-03-24 14:36:48 +08:00
|
|
|
case DECL_CXX_CTOR_INITIALIZERS:
|
|
|
|
Error("attempt to read a C++ ctor initializer record as a declaration");
|
|
|
|
return nullptr;
|
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;
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
case DECL_OBJC_TYPE_PARAM:
|
|
|
|
D = ObjCTypeParamDecl::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]))
|
2014-05-22 13:54:18 +08:00
|
|
|
return nullptr;
|
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);
|
2014-03-11 15:17:35 +08:00
|
|
|
for (const auto &Update : I->second) {
|
|
|
|
DeclContextInfo &Info = Update.second->DeclContextInfos[DC];
|
|
|
|
delete Info.NameLookupTableData;
|
|
|
|
Info.NameLookupTableData = Update.first;
|
|
|
|
}
|
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.
|
2014-04-30 10:24:17 +08:00
|
|
|
PendingUpdateRecords.push_back(std::make_pair(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;
|
2014-03-23 08:27:18 +08:00
|
|
|
bool WasInteresting = isConsumerInterestedIn(D, false);
|
2010-10-25 01:26:36 +08:00
|
|
|
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!");
|
2014-03-23 08:27:18 +08:00
|
|
|
|
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);
|
2014-03-23 08:27:18 +08:00
|
|
|
|
|
|
|
// We might have made this declaration interesting. If so, remember that
|
|
|
|
// we need to hand it off to the consumer.
|
|
|
|
if (!WasInteresting &&
|
|
|
|
isConsumerInterestedIn(D, Reader.hasPendingBody())) {
|
|
|
|
InterestingDecls.push_back(D);
|
|
|
|
WasInteresting = true;
|
|
|
|
}
|
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 {
|
2015-02-13 07:21:45 +08:00
|
|
|
/// \brief Module visitor class that finds all of the redeclarations of a
|
|
|
|
/// redeclarable declaration.
|
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;
|
2014-08-18 07:49:53 +08:00
|
|
|
llvm::SmallPtrSetImpl<Decl *> &Deserialized;
|
2011-12-22 09:48:48 +08:00
|
|
|
GlobalDeclID CanonID;
|
2013-01-13 03:30:44 +08:00
|
|
|
SmallVector<Decl *, 4> Chain;
|
2015-02-13 07:21:45 +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
|
|
|
public:
|
2011-12-22 09:48:48 +08:00
|
|
|
RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
|
2014-08-18 07:49:53 +08:00
|
|
|
llvm::SmallPtrSetImpl<Decl *> &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),
|
2015-02-13 07:21:45 +08:00
|
|
|
CanonID(CanonID) {
|
|
|
|
// Ensure that the canonical ID goes at the start of the chain.
|
|
|
|
addToChain(Reader.GetDecl(CanonID));
|
2012-01-18 02:13:45 +08:00
|
|
|
}
|
2015-02-13 07:21:45 +08:00
|
|
|
|
2015-05-20 18:29:23 +08:00
|
|
|
static ModuleManager::DFSPreorderControl
|
|
|
|
visitPreorder(ModuleFile &M, void *UserData) {
|
|
|
|
return static_cast<RedeclChainVisitor *>(UserData)->visitPreorder(M);
|
|
|
|
}
|
2015-02-13 07:21:45 +08:00
|
|
|
|
2015-05-20 18:29:23 +08:00
|
|
|
static bool visitPostorder(ModuleFile &M, void *UserData) {
|
|
|
|
return static_cast<RedeclChainVisitor *>(UserData)->visitPostorder(M);
|
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
|
|
|
}
|
2015-02-13 07:21:45 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
void addToChain(Decl *D) {
|
|
|
|
if (!D)
|
|
|
|
return;
|
2015-02-13 07:21:45 +08:00
|
|
|
|
2012-08-22 23:37:55 +08:00
|
|
|
if (Deserialized.erase(D))
|
2012-01-16 00:58:34 +08:00
|
|
|
Chain.push_back(D);
|
|
|
|
}
|
2015-02-13 07:21:45 +08:00
|
|
|
|
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;
|
2015-02-13 07:21:45 +08:00
|
|
|
|
|
|
|
// If the search decl was from this module, add it to the chain before any
|
|
|
|
// of its redeclarations in this module or users of it, and after any from
|
|
|
|
// imported modules.
|
|
|
|
if (CanonID != GlobalID && Reader.isDeclIDFromModule(GlobalID, M))
|
|
|
|
addToChain(Reader.GetDecl(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
|
|
|
// Perform a binary search to find the local redeclarations for this
|
|
|
|
// declaration (if any).
|
2014-03-15 22:21:58 +08:00
|
|
|
const LocalRedeclarationsInfo Compare = { ID, 0 };
|
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
|
|
|
const LocalRedeclarationsInfo *Result
|
2012-01-16 00:58:34 +08:00
|
|
|
= std::lower_bound(M.RedeclarationsMap,
|
|
|
|
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
|
2014-03-15 22:21:58 +08:00
|
|
|
Compare);
|
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
|
|
|
}
|
2015-05-20 18:29:23 +08:00
|
|
|
|
|
|
|
bool needsToVisitImports(ModuleFile &M, GlobalDeclID GlobalID) {
|
|
|
|
DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
|
|
|
|
if (!ID)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const LocalRedeclarationsInfo Compare = {ID, 0};
|
|
|
|
const LocalRedeclarationsInfo *Result = std::lower_bound(
|
|
|
|
M.RedeclarationsMap,
|
|
|
|
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare);
|
|
|
|
if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
|
|
|
|
Result->FirstID != ID) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
unsigned Offset = Result->Offset;
|
|
|
|
unsigned N = M.RedeclarationChains[Offset];
|
|
|
|
// We don't need to visit a module or any of its imports if we've already
|
|
|
|
// deserialized the redecls from this module.
|
|
|
|
return N != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleManager::DFSPreorderControl visitPreorder(ModuleFile &M) {
|
|
|
|
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) {
|
|
|
|
if (needsToVisitImports(M, SearchDecls[I]))
|
|
|
|
return ModuleManager::Continue;
|
|
|
|
}
|
|
|
|
return ModuleManager::SkipImports;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool visitPostorder(ModuleFile &M) {
|
2011-12-22 09:48:48 +08:00
|
|
|
// Visit each of the declarations.
|
|
|
|
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
|
|
|
|
searchForID(M, SearchDecls[I]);
|
2014-07-15 11:37:06 +08:00
|
|
|
// FIXME: If none of the SearchDecls had local IDs in this module, can
|
|
|
|
// we avoid searching any ancestor module files?
|
2015-04-17 16:01:41 +08:00
|
|
|
return false;
|
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
|
|
|
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
|
|
|
}
|
|
|
|
};
|
2015-06-23 07:07:51 +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
|
|
|
|
2015-03-06 07:24:12 +08:00
|
|
|
void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
|
|
|
|
// The decl might have been merged into something else after being added to
|
|
|
|
// our list. If it was, just skip it.
|
|
|
|
if (!CanonDecl->isCanonicalDecl())
|
|
|
|
return;
|
|
|
|
|
2011-12-22 09:48:48 +08:00
|
|
|
// Determine the set of declaration IDs we'll be searching for.
|
2015-03-06 07:24:12 +08:00
|
|
|
SmallVector<DeclID, 16> SearchDecls;
|
|
|
|
GlobalDeclID CanonID = CanonDecl->getGlobalID();
|
|
|
|
if (CanonID)
|
|
|
|
SearchDecls.push_back(CanonDecl->getGlobalID()); // Always first.
|
|
|
|
MergedDeclsMap::iterator MergedPos = MergedDecls.find(CanonDecl);
|
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());
|
2015-03-06 07:24:12 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
// Build up the list of redeclarations.
|
|
|
|
RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
|
2015-05-20 18:29:23 +08:00
|
|
|
ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visitPreorder,
|
|
|
|
&RedeclChainVisitor::visitPostorder, &Visitor);
|
2015-03-06 07:24:12 +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
|
|
|
// Retrieve the chains.
|
2012-01-16 00:58:34 +08:00
|
|
|
ArrayRef<Decl *> Chain = Visitor.getChain();
|
2015-05-20 18:29:23 +08:00
|
|
|
if (Chain.empty() || (Chain.size() == 1 && Chain[0] == CanonDecl))
|
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;
|
2015-02-28 13:57:02 +08:00
|
|
|
|
2012-01-16 00:58:34 +08:00
|
|
|
// Hook up the chains.
|
2015-02-28 13:57:02 +08:00
|
|
|
//
|
|
|
|
// FIXME: We have three different dispatches on decl kind here; maybe
|
|
|
|
// we should instead generate one loop per kind and dispatch up-front?
|
|
|
|
Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
|
|
|
|
if (!MostRecent)
|
|
|
|
MostRecent = CanonDecl;
|
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
|
|
|
|
2015-03-23 11:25:59 +08:00
|
|
|
ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent, CanonDecl);
|
2012-01-16 00:58:34 +08:00
|
|
|
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
|
|
|
}
|
2015-02-28 13:57:02 +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 {
|
|
|
|
/// \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;
|
2014-08-18 07:49:53 +08:00
|
|
|
llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized;
|
2012-01-27 09:47:08 +08:00
|
|
|
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,
|
2014-08-18 07:49:53 +08:00
|
|
|
llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
|
2012-01-27 09:47:08 +08:00
|
|
|
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),
|
2014-05-22 13:54:18 +08:00
|
|
|
Tail(nullptr)
|
2012-01-27 09:47:08 +08:00
|
|
|
{
|
|
|
|
// Populate the name -> category map with the set of known categories.
|
2014-03-14 05:35:02 +08:00
|
|
|
for (auto *Cat : Interface->known_categories()) {
|
2012-01-27 09:47:08 +08:00
|
|
|
if (Cat->getDeclName())
|
2014-03-14 05:35:02 +08:00
|
|
|
NameCategoryMap[Cat->getDeclName()] = Cat;
|
2012-01-27 09:47:08 +08:00
|
|
|
|
|
|
|
// Keep track of the tail of the category list.
|
2014-03-14 05:35:02 +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).
|
2014-03-15 22:21:58 +08:00
|
|
|
const ObjCCategoriesInfo Compare = { LocalID, 0 };
|
2012-01-27 09:47:08 +08:00
|
|
|
const ObjCCategoriesInfo *Result
|
|
|
|
= std::lower_bound(M.ObjCCategoriesMap,
|
|
|
|
M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
|
2014-03-15 22:21:58 +08:00
|
|
|
Compare);
|
2012-01-27 09:47:08 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
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
|
|
|
|
2014-08-08 04:58:41 +08:00
|
|
|
template<typename DeclT, typename Fn>
|
|
|
|
static void forAllLaterRedecls(DeclT *D, Fn F) {
|
|
|
|
F(D);
|
|
|
|
|
|
|
|
// Check whether we've already merged D into its redeclaration chain.
|
|
|
|
// MostRecent may or may not be nullptr if D has not been merged. If
|
|
|
|
// not, walk the merged redecl chain and see if it's there.
|
|
|
|
auto *MostRecent = D->getMostRecentDecl();
|
|
|
|
bool Found = false;
|
|
|
|
for (auto *Redecl = MostRecent; Redecl && !Found;
|
|
|
|
Redecl = Redecl->getPreviousDecl())
|
|
|
|
Found = (Redecl == D);
|
|
|
|
|
|
|
|
// If this declaration is merged, apply the functor to all later decls.
|
|
|
|
if (Found) {
|
|
|
|
for (auto *Redecl = MostRecent; Redecl != D;
|
|
|
|
Redecl = Redecl->getPreviousDecl())
|
|
|
|
F(Redecl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
while (Idx < Record.size()) {
|
|
|
|
switch ((DeclUpdateKind)Record[Idx++]) {
|
2014-04-19 11:48:30 +08:00
|
|
|
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
|
2015-01-22 11:50:31 +08:00
|
|
|
auto *RD = cast<CXXRecordDecl>(D);
|
2014-08-08 04:58:41 +08:00
|
|
|
// FIXME: If we also have an update record for instantiating the
|
|
|
|
// definition of D, we need that to happen before we get here.
|
2014-04-19 11:48:30 +08:00
|
|
|
Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
|
|
|
|
assert(MD && "couldn't read decl from update record");
|
2014-08-01 09:56:39 +08:00
|
|
|
// FIXME: We should call addHiddenDecl instead, to add the member
|
|
|
|
// to its DeclContext.
|
2015-01-22 11:50:31 +08:00
|
|
|
RD->addedMember(MD);
|
|
|
|
|
|
|
|
// If we've added a new special member to a class definition that is not
|
|
|
|
// the canonical definition, then we need special member lookups in the
|
|
|
|
// canonical definition to also look into our class.
|
|
|
|
auto *DD = RD->DefinitionData.getNotUpdated();
|
|
|
|
if (DD && DD->Definition != RD) {
|
|
|
|
auto &Merged = Reader.MergedLookups[DD->Definition];
|
|
|
|
// FIXME: Avoid the linear-time scan here.
|
|
|
|
if (std::find(Merged.begin(), Merged.end(), RD) == Merged.end())
|
|
|
|
Merged.push_back(RD);
|
|
|
|
}
|
2010-10-25 01:26:54 +08:00
|
|
|
break;
|
2014-04-19 11:48:30 +08:00
|
|
|
}
|
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.
|
2014-10-22 10:05:46 +08:00
|
|
|
if (ModuleFile.Kind != MK_ImplicitModule &&
|
|
|
|
ModuleFile.Kind != MK_ExplicitModule) {
|
2012-01-10 02:07:24 +08:00
|
|
|
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
|
|
|
|
2014-08-08 02:53:08 +08:00
|
|
|
case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
|
2014-03-23 07:33:22 +08:00
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(D);
|
2014-04-19 11:48:30 +08:00
|
|
|
if (Reader.PendingBodies[FD]) {
|
2014-03-23 07:33:22 +08:00
|
|
|
// FIXME: Maybe check for ODR violations.
|
2014-04-19 11:48:30 +08:00
|
|
|
// It's safe to stop now because this update record is always last.
|
|
|
|
return;
|
|
|
|
}
|
2014-03-23 07:33:22 +08:00
|
|
|
|
2014-05-29 11:15:31 +08:00
|
|
|
if (Record[Idx++]) {
|
|
|
|
// Maintain AST consistency: any later redeclarations of this function
|
|
|
|
// are inline if this one is. (We might have merged another declaration
|
|
|
|
// into this one.)
|
2014-08-08 04:58:41 +08:00
|
|
|
forAllLaterRedecls(FD, [](FunctionDecl *FD) {
|
|
|
|
FD->setImplicitlyInline();
|
|
|
|
});
|
2014-05-29 11:15:31 +08:00
|
|
|
}
|
2014-03-23 07:33:22 +08:00
|
|
|
FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
2015-03-24 14:36:48 +08:00
|
|
|
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
|
|
|
|
CD->NumCtorInitializers = Record[Idx++];
|
|
|
|
if (CD->NumCtorInitializers)
|
|
|
|
CD->CtorInitializers =
|
|
|
|
Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
|
|
|
|
}
|
2014-03-23 07:33:22 +08:00
|
|
|
// Store the offset of the body so we can lazily load it later.
|
|
|
|
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
|
2014-03-23 08:27:18 +08:00
|
|
|
HasPendingBody = true;
|
2014-03-23 07:33:22 +08:00
|
|
|
assert(Idx == Record.size() && "lazy body must be last");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-04-19 11:48:30 +08:00
|
|
|
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
|
|
|
|
auto *RD = cast<CXXRecordDecl>(D);
|
2015-02-03 11:32:14 +08:00
|
|
|
auto *OldDD = RD->DefinitionData.getNotUpdated();
|
|
|
|
bool HadRealDefinition =
|
2015-02-04 09:23:46 +08:00
|
|
|
OldDD && (OldDD->Definition != RD ||
|
|
|
|
!Reader.PendingFakeDefinitionData.count(OldDD));
|
2015-02-03 11:32:14 +08:00
|
|
|
ReadCXXRecordDefinition(RD, /*Update*/true);
|
|
|
|
|
2014-04-19 11:48:30 +08:00
|
|
|
// Visible update is handled separately.
|
|
|
|
uint64_t LexicalOffset = Record[Idx++];
|
2015-01-24 09:07:20 +08:00
|
|
|
if (!HadRealDefinition && LexicalOffset) {
|
2014-04-19 11:48:30 +08:00
|
|
|
RD->setHasExternalLexicalStorage(true);
|
|
|
|
Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
|
2015-02-03 11:32:14 +08:00
|
|
|
std::make_pair(LexicalOffset, 0),
|
|
|
|
ModuleFile.DeclContextInfos[RD]);
|
|
|
|
Reader.PendingFakeDefinitionData.erase(OldDD);
|
2014-04-19 11:48:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
auto TSK = (TemplateSpecializationKind)Record[Idx++];
|
|
|
|
SourceLocation POI = Reader.ReadSourceLocation(ModuleFile, Record, Idx);
|
|
|
|
if (MemberSpecializationInfo *MSInfo =
|
|
|
|
RD->getMemberSpecializationInfo()) {
|
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
|
|
|
MSInfo->setPointOfInstantiation(POI);
|
|
|
|
} else {
|
|
|
|
ClassTemplateSpecializationDecl *Spec =
|
|
|
|
cast<ClassTemplateSpecializationDecl>(RD);
|
|
|
|
Spec->setTemplateSpecializationKind(TSK);
|
|
|
|
Spec->setPointOfInstantiation(POI);
|
2014-05-23 04:59:29 +08:00
|
|
|
|
|
|
|
if (Record[Idx++]) {
|
|
|
|
auto PartialSpec =
|
|
|
|
ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx);
|
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
|
|
|
auto *TemplArgList = TemplateArgumentList::CreateCopy(
|
|
|
|
Reader.getContext(), TemplArgs.data(), TemplArgs.size());
|
2014-08-14 11:30:27 +08:00
|
|
|
|
|
|
|
// FIXME: If we already have a partial specialization set,
|
|
|
|
// check that it matches.
|
|
|
|
if (!Spec->getSpecializedTemplateOrPartial()
|
|
|
|
.is<ClassTemplatePartialSpecializationDecl *>())
|
|
|
|
Spec->setInstantiationOf(PartialSpec, TemplArgList);
|
2014-05-23 04:59:29 +08:00
|
|
|
}
|
2014-04-19 11:48:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RD->setTagKind((TagTypeKind)Record[Idx++]);
|
|
|
|
RD->setLocation(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
|
|
|
RD->setLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
|
|
|
RD->setRBraceLoc(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
|
|
|
|
|
|
|
if (Record[Idx++]) {
|
|
|
|
AttrVec Attrs;
|
|
|
|
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
|
|
|
D->setAttrsImpl(Attrs, Reader.getContext());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-03-10 09:41:22 +08:00
|
|
|
case UPD_CXX_RESOLVED_DTOR_DELETE: {
|
|
|
|
// Set the 'operator delete' directly to avoid emitting another update
|
|
|
|
// record.
|
|
|
|
auto *Del = Reader.ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
|
|
|
|
auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
|
|
|
|
// FIXME: Check consistency if we have an old and new operator delete.
|
|
|
|
if (!First->OperatorDelete)
|
|
|
|
First->OperatorDelete = Del;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-21 05:47:22 +08:00
|
|
|
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
|
2014-08-01 05:57:55 +08:00
|
|
|
FunctionProtoType::ExceptionSpecInfo ESI;
|
2014-08-01 07:46:44 +08:00
|
|
|
SmallVector<QualType, 8> ExceptionStorage;
|
2014-08-01 05:57:55 +08:00
|
|
|
Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx);
|
2015-03-23 11:25:59 +08:00
|
|
|
|
|
|
|
// Update this declaration's exception specification, if needed.
|
|
|
|
auto *FD = cast<FunctionDecl>(D);
|
|
|
|
auto *FPT = FD->getType()->castAs<FunctionProtoType>();
|
|
|
|
// FIXME: If the exception specification is already present, check that it
|
|
|
|
// matches.
|
|
|
|
if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
|
2014-08-01 07:46:44 +08:00
|
|
|
FD->setType(Reader.Context.getFunctionType(
|
|
|
|
FPT->getReturnType(), FPT->getParamTypes(),
|
|
|
|
FPT->getExtProtoInfo().withExceptionSpec(ESI)));
|
2015-03-23 11:25:59 +08:00
|
|
|
|
|
|
|
// When we get to the end of deserializing, see if there are other decls
|
|
|
|
// that we need to propagate this exception specification onto.
|
|
|
|
Reader.PendingExceptionSpecUpdates.insert(
|
|
|
|
std::make_pair(FD->getCanonicalDecl(), FD));
|
2014-08-01 07:46:44 +08:00
|
|
|
}
|
2014-03-21 05:47:22 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-11 13:45:24 +08:00
|
|
|
case UPD_CXX_DEDUCED_RETURN_TYPE: {
|
2014-08-08 04:58:41 +08:00
|
|
|
// FIXME: Also do this when merging redecls.
|
|
|
|
QualType DeducedResultType = Reader.readType(ModuleFile, Record, Idx);
|
|
|
|
for (auto *Redecl : merged_redecls(D)) {
|
|
|
|
// FIXME: If the return type is already deduced, check that it matches.
|
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(Redecl);
|
|
|
|
Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType);
|
|
|
|
}
|
2013-05-11 13:45:24 +08:00
|
|
|
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.
|
2014-06-17 04:26:19 +08:00
|
|
|
|
|
|
|
// Maintain AST consistency: any later redeclarations are used too.
|
2014-08-08 04:58:41 +08:00
|
|
|
forAllLaterRedecls(D, [](Decl *D) { D->Used = true; });
|
2013-09-05 08:02:25 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-03-21 09:48:23 +08:00
|
|
|
|
|
|
|
case UPD_MANGLING_NUMBER:
|
|
|
|
Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record[Idx++]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UPD_STATIC_LOCAL_NUMBER:
|
|
|
|
Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
|
|
|
|
break;
|
2015-03-26 12:09:53 +08:00
|
|
|
|
2014-11-11 12:05:39 +08:00
|
|
|
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
|
|
|
|
D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
|
|
|
|
Reader.Context, ReadSourceRange(Record, Idx)));
|
|
|
|
break;
|
2015-03-26 12:09:53 +08:00
|
|
|
|
2015-06-26 13:28:36 +08:00
|
|
|
case UPD_DECL_EXPORTED: {
|
2015-03-26 12:09:53 +08:00
|
|
|
unsigned SubmoduleID = readSubmoduleID(Record, Idx);
|
2015-06-20 09:05:19 +08:00
|
|
|
auto *Exported = cast<NamedDecl>(D);
|
|
|
|
if (auto *TD = dyn_cast<TagDecl>(Exported))
|
|
|
|
Exported = TD->getDefinition();
|
2015-03-26 12:09:53 +08:00
|
|
|
Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr;
|
2015-05-16 04:05:43 +08:00
|
|
|
if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
|
|
|
|
// FIXME: This doesn't send the right notifications if there are
|
|
|
|
// ASTMutationListeners other than an ASTWriter.
|
2015-06-26 05:42:33 +08:00
|
|
|
Reader.getContext().mergeDefinitionIntoModule(
|
|
|
|
cast<NamedDecl>(Exported), Owner,
|
|
|
|
/*NotifyListeners*/ false);
|
|
|
|
Reader.PendingMergedDefinitionsToDeduplicate.insert(
|
|
|
|
cast<NamedDecl>(Exported));
|
2015-05-16 04:05:43 +08:00
|
|
|
} else if (Owner && Owner->NameVisibility != Module::AllVisible) {
|
2015-03-26 12:09:53 +08:00
|
|
|
// If Owner is made visible at some later point, make this declaration
|
|
|
|
// visible too.
|
2015-06-26 05:42:33 +08:00
|
|
|
Reader.HiddenNamesMap[Owner].push_back(Exported);
|
2015-03-26 12:09:53 +08:00
|
|
|
} else {
|
|
|
|
// The declaration is now visible.
|
2015-06-26 05:42:33 +08:00
|
|
|
Exported->Hidden = false;
|
2015-03-26 12:09:53 +08:00
|
|
|
}
|
|
|
|
break;
|
2010-10-25 01:26:50 +08:00
|
|
|
}
|
2015-06-26 13:28:36 +08:00
|
|
|
|
|
|
|
case UPD_ADDED_ATTR_TO_RECORD:
|
|
|
|
AttrVec Attrs;
|
|
|
|
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
|
|
|
assert(Attrs.size() == 1);
|
|
|
|
D->addAttr(Attrs[0]);
|
|
|
|
break;
|
|
|
|
}
|
2010-10-25 01:26:50 +08:00
|
|
|
}
|
2010-10-25 01:26:36 +08:00
|
|
|
}
|